blob: 5531aaeaa71be154ff66d7144310eb6fd8a8ccf0 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002 * IEEE 802.11 RSN / WPA Authenticator
Sunil Ravia04bd252022-05-02 22:54:18 -07003 * Copyright (c) 2004-2022, Jouni Malinen <j@w1.fi>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 */
8
9#include "utils/includes.h"
10
11#include "utils/common.h"
12#include "utils/eloop.h"
13#include "utils/state_machine.h"
Dmitry Shmidtcf32e602014-01-28 10:57:39 -080014#include "utils/bitfield.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070015#include "common/ieee802_11_defs.h"
Hai Shalom74f70d42019-02-11 14:42:39 -080016#include "common/ocv.h"
Hai Shalom4fbc08f2020-05-18 12:37:00 -070017#include "common/dpp.h"
Hai Shalom899fcc72020-10-19 14:38:18 -070018#include "common/wpa_ctrl.h"
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -080019#include "crypto/aes.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070020#include "crypto/aes_wrap.h"
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -080021#include "crypto/aes_siv.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070022#include "crypto/crypto.h"
23#include "crypto/sha1.h"
24#include "crypto/sha256.h"
Roshan Pius3a1667e2018-07-03 15:17:14 -070025#include "crypto/sha384.h"
Sunil Ravi38ad1ed2023-01-17 23:58:31 +000026#include "crypto/sha512.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070027#include "crypto/random.h"
28#include "eapol_auth/eapol_auth_sm.h"
Hai Shalom74f70d42019-02-11 14:42:39 -080029#include "drivers/driver.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070030#include "ap_config.h"
31#include "ieee802_11.h"
Sunil Ravi2a14cf12023-11-21 00:54:38 +000032#include "sta_info.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070033#include "wpa_auth.h"
34#include "pmksa_cache_auth.h"
35#include "wpa_auth_i.h"
36#include "wpa_auth_ie.h"
37
38#define STATE_MACHINE_DATA struct wpa_state_machine
39#define STATE_MACHINE_DEBUG_PREFIX "WPA"
Sunil Raviaf8751c2023-03-29 11:35:17 -070040#define STATE_MACHINE_ADDR wpa_auth_get_spa(sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070041
42
43static void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx);
44static int wpa_sm_step(struct wpa_state_machine *sm);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070045static int wpa_verify_key_mic(int akmp, size_t pmk_len, struct wpa_ptk *PTK,
46 u8 *data, size_t data_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -080047#ifdef CONFIG_FILS
48static int wpa_aead_decrypt(struct wpa_state_machine *sm, struct wpa_ptk *ptk,
49 u8 *buf, size_t buf_len, u16 *_key_data_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070050static struct wpabuf * fils_prepare_plainbuf(struct wpa_state_machine *sm,
51 const struct wpabuf *hlp);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -080052#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070053static void wpa_sm_call_step(void *eloop_ctx, void *timeout_ctx);
54static void wpa_group_sm_step(struct wpa_authenticator *wpa_auth,
55 struct wpa_group *group);
56static void wpa_request_new_ptk(struct wpa_state_machine *sm);
57static int wpa_gtk_update(struct wpa_authenticator *wpa_auth,
58 struct wpa_group *group);
59static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth,
60 struct wpa_group *group);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080061static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080062 const u8 *pmk, unsigned int pmk_len,
Sunil Raviaf8751c2023-03-29 11:35:17 -070063 struct wpa_ptk *ptk, int force_sha256,
64 u8 *pmk_r0, u8 *pmk_r1, u8 *pmk_r0_name,
Sunil Ravi7f769292024-07-23 22:21:32 +000065 size_t *key_len, bool no_kdk);
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070066static void wpa_group_free(struct wpa_authenticator *wpa_auth,
67 struct wpa_group *group);
68static void wpa_group_get(struct wpa_authenticator *wpa_auth,
69 struct wpa_group *group);
70static void wpa_group_put(struct wpa_authenticator *wpa_auth,
71 struct wpa_group *group);
Hai Shalomfdcde762020-04-02 11:19:20 -070072static int ieee80211w_kde_len(struct wpa_state_machine *sm);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -080073static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos);
Sunil Ravi7f769292024-07-23 22:21:32 +000074static void wpa_group_update_gtk(struct wpa_authenticator *wpa_auth,
75 struct wpa_group *group);
76
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070077
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070078static const u32 eapol_key_timeout_first = 100; /* ms */
79static const u32 eapol_key_timeout_subseq = 1000; /* ms */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080080static const u32 eapol_key_timeout_first_group = 500; /* ms */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070081static const u32 eapol_key_timeout_no_retrans = 4000; /* ms */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070082
83/* TODO: make these configurable */
84static const int dot11RSNAConfigPMKLifetime = 43200;
85static const int dot11RSNAConfigPMKReauthThreshold = 70;
86static const int dot11RSNAConfigSATimeout = 60;
87
88
Sunil Raviaf8751c2023-03-29 11:35:17 -070089static const u8 * wpa_auth_get_aa(const struct wpa_state_machine *sm)
90{
Sunil Ravi2a14cf12023-11-21 00:54:38 +000091#ifdef CONFIG_IEEE80211BE
92 if (sm->mld_assoc_link_id >= 0)
Sunil Ravi7f769292024-07-23 22:21:32 +000093 return sm->wpa_auth->mld_addr;
Sunil Ravi2a14cf12023-11-21 00:54:38 +000094#endif /* CONFIG_IEEE80211BE */
Sunil Raviaf8751c2023-03-29 11:35:17 -070095 return sm->wpa_auth->addr;
96}
97
98
99static const u8 * wpa_auth_get_spa(const struct wpa_state_machine *sm)
100{
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000101#ifdef CONFIG_IEEE80211BE
102 if (sm->mld_assoc_link_id >= 0)
103 return sm->peer_mld_addr;
104#endif /* CONFIG_IEEE80211BE */
Sunil Raviaf8751c2023-03-29 11:35:17 -0700105 return sm->addr;
106}
107
108
Sunil Ravi7f769292024-07-23 22:21:32 +0000109static void wpa_gkeydone_sta(struct wpa_state_machine *sm)
110{
111#ifdef CONFIG_IEEE80211BE
112 int link_id;
113#endif /* CONFIG_IEEE80211BE */
114
Sunil Ravic0f5d412024-09-11 22:12:49 +0000115 sm->group->GKeyDoneStations--;
Sunil Ravi7f769292024-07-23 22:21:32 +0000116 sm->GUpdateStationKeys = false;
117
118#ifdef CONFIG_IEEE80211BE
119 for_each_sm_auth(sm, link_id)
120 sm->mld_links[link_id].wpa_auth->group->GKeyDoneStations--;
121#endif /* CONFIG_IEEE80211BE */
122}
123
124
125#ifdef CONFIG_IEEE80211BE
126
127void wpa_release_link_auth_ref(struct wpa_state_machine *sm,
128 int release_link_id)
129{
130 int link_id;
131
132 if (!sm || release_link_id >= MAX_NUM_MLD_LINKS)
133 return;
134
135 for_each_sm_auth(sm, link_id) {
Sunil Ravi79e6c4f2025-01-04 00:47:06 +0000136 if (link_id == release_link_id)
Sunil Ravi7f769292024-07-23 22:21:32 +0000137 sm->mld_links[link_id].wpa_auth = NULL;
Sunil Ravi7f769292024-07-23 22:21:32 +0000138 }
139}
140
141
142struct wpa_get_link_auth_ctx {
143 const u8 *addr;
144 const u8 *mld_addr;
145 int link_id;
146 struct wpa_authenticator *wpa_auth;
147};
148
149static int wpa_get_link_sta_auth(struct wpa_authenticator *wpa_auth, void *data)
150{
151 struct wpa_get_link_auth_ctx *ctx = data;
152
153 if (!wpa_auth->is_ml)
154 return 0;
155
156 if (ctx->mld_addr &&
157 !ether_addr_equal(wpa_auth->mld_addr, ctx->mld_addr))
158 return 0;
159
160 if ((ctx->addr && ether_addr_equal(wpa_auth->addr, ctx->addr)) ||
161 (ctx->link_id > -1 && wpa_auth->is_ml &&
162 wpa_auth->link_id == ctx->link_id)) {
163 ctx->wpa_auth = wpa_auth;
164 return 1;
165
166 }
167 return 0;
168}
169
170
171static struct wpa_authenticator *
172wpa_get_link_auth(struct wpa_authenticator *wpa_auth, int link_id)
173{
174 struct wpa_get_link_auth_ctx ctx;
175
176 ctx.addr = NULL;
177 ctx.mld_addr = wpa_auth->mld_addr;
178 ctx.link_id = link_id;
179 ctx.wpa_auth = NULL;
180 wpa_auth_for_each_auth(wpa_auth, wpa_get_link_sta_auth, &ctx);
181 return ctx.wpa_auth;
182}
183
184
185static int wpa_get_primary_auth_cb(struct wpa_authenticator *wpa_auth,
186 void *data)
187{
188 struct wpa_get_link_auth_ctx *ctx = data;
189
190 if (!wpa_auth->is_ml ||
191 !ether_addr_equal(wpa_auth->mld_addr, ctx->addr) ||
192 !wpa_auth->primary_auth)
193 return 0;
194
195 ctx->wpa_auth = wpa_auth;
196 return 1;
197}
198
199#endif /* CONFIG_IEEE80211BE */
200
201
202static struct wpa_authenticator *
203wpa_get_primary_auth(struct wpa_authenticator *wpa_auth)
204{
205#ifdef CONFIG_IEEE80211BE
206 struct wpa_get_link_auth_ctx ctx;
207
208 if (!wpa_auth || !wpa_auth->is_ml || wpa_auth->primary_auth)
209 return wpa_auth;
210
211 ctx.addr = wpa_auth->mld_addr;
212 ctx.wpa_auth = NULL;
213 wpa_auth_for_each_auth(wpa_auth, wpa_get_primary_auth_cb, &ctx);
214
215 return ctx.wpa_auth;
216#else /* CONFIG_IEEE80211BE */
217 return wpa_auth;
218#endif /* CONFIG_IEEE80211BE */
219}
220
221
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800222static inline int wpa_auth_mic_failure_report(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700223 struct wpa_authenticator *wpa_auth, const u8 *addr)
224{
Paul Stewart092955c2017-02-06 09:13:09 -0800225 if (wpa_auth->cb->mic_failure_report)
226 return wpa_auth->cb->mic_failure_report(wpa_auth->cb_ctx, addr);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800227 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700228}
229
230
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700231static inline void wpa_auth_psk_failure_report(
232 struct wpa_authenticator *wpa_auth, const u8 *addr)
233{
Paul Stewart092955c2017-02-06 09:13:09 -0800234 if (wpa_auth->cb->psk_failure_report)
235 wpa_auth->cb->psk_failure_report(wpa_auth->cb_ctx, addr);
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700236}
237
238
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700239static inline void wpa_auth_set_eapol(struct wpa_authenticator *wpa_auth,
240 const u8 *addr, wpa_eapol_variable var,
241 int value)
242{
Paul Stewart092955c2017-02-06 09:13:09 -0800243 if (wpa_auth->cb->set_eapol)
244 wpa_auth->cb->set_eapol(wpa_auth->cb_ctx, addr, var, value);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700245}
246
247
248static inline int wpa_auth_get_eapol(struct wpa_authenticator *wpa_auth,
249 const u8 *addr, wpa_eapol_variable var)
250{
Hai Shalomfdcde762020-04-02 11:19:20 -0700251 if (!wpa_auth->cb->get_eapol)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700252 return -1;
Paul Stewart092955c2017-02-06 09:13:09 -0800253 return wpa_auth->cb->get_eapol(wpa_auth->cb_ctx, addr, var);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700254}
255
256
257static inline const u8 * wpa_auth_get_psk(struct wpa_authenticator *wpa_auth,
Dmitry Shmidt391c59f2013-09-03 12:16:28 -0700258 const u8 *addr,
259 const u8 *p2p_dev_addr,
Hai Shalom021b0b52019-04-10 11:17:58 -0700260 const u8 *prev_psk, size_t *psk_len,
261 int *vlan_id)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700262{
Hai Shalomfdcde762020-04-02 11:19:20 -0700263 if (!wpa_auth->cb->get_psk)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700264 return NULL;
Paul Stewart092955c2017-02-06 09:13:09 -0800265 return wpa_auth->cb->get_psk(wpa_auth->cb_ctx, addr, p2p_dev_addr,
Hai Shalom021b0b52019-04-10 11:17:58 -0700266 prev_psk, psk_len, vlan_id);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700267}
268
269
270static inline int wpa_auth_get_msk(struct wpa_authenticator *wpa_auth,
271 const u8 *addr, u8 *msk, size_t *len)
272{
Hai Shalomfdcde762020-04-02 11:19:20 -0700273 if (!wpa_auth->cb->get_msk)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700274 return -1;
Paul Stewart092955c2017-02-06 09:13:09 -0800275 return wpa_auth->cb->get_msk(wpa_auth->cb_ctx, addr, msk, len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700276}
277
278
279static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth,
280 int vlan_id,
281 enum wpa_alg alg, const u8 *addr, int idx,
Hai Shalomfdcde762020-04-02 11:19:20 -0700282 u8 *key, size_t key_len,
283 enum key_flag key_flag)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700284{
Hai Shalomfdcde762020-04-02 11:19:20 -0700285 if (!wpa_auth->cb->set_key)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700286 return -1;
Paul Stewart092955c2017-02-06 09:13:09 -0800287 return wpa_auth->cb->set_key(wpa_auth->cb_ctx, vlan_id, alg, addr, idx,
Hai Shalomfdcde762020-04-02 11:19:20 -0700288 key, key_len, key_flag);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700289}
290
291
Sunil Ravi89eba102022-09-13 21:04:37 -0700292#ifdef CONFIG_PASN
293static inline int wpa_auth_set_ltf_keyseed(struct wpa_authenticator *wpa_auth,
294 const u8 *peer_addr,
295 const u8 *ltf_keyseed,
296 size_t ltf_keyseed_len)
297{
298 if (!wpa_auth->cb->set_ltf_keyseed)
299 return -1;
300 return wpa_auth->cb->set_ltf_keyseed(wpa_auth->cb_ctx, peer_addr,
301 ltf_keyseed, ltf_keyseed_len);
302}
303#endif /* CONFIG_PASN */
304
305
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700306static inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth,
307 const u8 *addr, int idx, u8 *seq)
308{
Hai Shalomfdcde762020-04-02 11:19:20 -0700309 int res;
310
311 if (!wpa_auth->cb->get_seqnum)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700312 return -1;
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000313#ifdef CONFIG_TESTING_OPTIONS
314 os_memset(seq, 0, WPA_KEY_RSC_LEN);
315#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomfdcde762020-04-02 11:19:20 -0700316 res = wpa_auth->cb->get_seqnum(wpa_auth->cb_ctx, addr, idx, seq);
317#ifdef CONFIG_TESTING_OPTIONS
318 if (!addr && idx < 4 && wpa_auth->conf.gtk_rsc_override_set) {
319 wpa_printf(MSG_DEBUG,
320 "TESTING: Override GTK RSC %016llx --> %016llx",
321 (long long unsigned) WPA_GET_LE64(seq),
322 (long long unsigned)
323 WPA_GET_LE64(wpa_auth->conf.gtk_rsc_override));
324 os_memcpy(seq, wpa_auth->conf.gtk_rsc_override,
325 WPA_KEY_RSC_LEN);
326 }
327 if (!addr && idx >= 4 && idx <= 5 &&
328 wpa_auth->conf.igtk_rsc_override_set) {
329 wpa_printf(MSG_DEBUG,
330 "TESTING: Override IGTK RSC %016llx --> %016llx",
331 (long long unsigned) WPA_GET_LE64(seq),
332 (long long unsigned)
333 WPA_GET_LE64(wpa_auth->conf.igtk_rsc_override));
334 os_memcpy(seq, wpa_auth->conf.igtk_rsc_override,
335 WPA_KEY_RSC_LEN);
336 }
337#endif /* CONFIG_TESTING_OPTIONS */
338 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700339}
340
341
342static inline int
343wpa_auth_send_eapol(struct wpa_authenticator *wpa_auth, const u8 *addr,
344 const u8 *data, size_t data_len, int encrypt)
345{
Hai Shalomfdcde762020-04-02 11:19:20 -0700346 if (!wpa_auth->cb->send_eapol)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700347 return -1;
Kai Shie75b0652020-11-24 20:31:29 -0800348#ifdef CONFIG_TESTING_OPTIONS
349 if (wpa_auth->conf.skip_send_eapol)
350 return 0;
351#endif
Paul Stewart092955c2017-02-06 09:13:09 -0800352 return wpa_auth->cb->send_eapol(wpa_auth->cb_ctx, addr, data, data_len,
353 encrypt);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700354}
355
356
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800357#ifdef CONFIG_MESH
358static inline int wpa_auth_start_ampe(struct wpa_authenticator *wpa_auth,
359 const u8 *addr)
360{
Hai Shalomfdcde762020-04-02 11:19:20 -0700361 if (!wpa_auth->cb->start_ampe)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800362 return -1;
Paul Stewart092955c2017-02-06 09:13:09 -0800363 return wpa_auth->cb->start_ampe(wpa_auth->cb_ctx, addr);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800364}
365#endif /* CONFIG_MESH */
366
367
Sunil Ravi79e6c4f2025-01-04 00:47:06 +0000368static inline int wpa_auth_get_drv_flags(struct wpa_authenticator *wpa_auth,
369 u64 *drv_flags, u64 *drv_flags2)
370{
371 if (!wpa_auth->cb->get_drv_flags)
372 return -1;
373 return wpa_auth->cb->get_drv_flags(wpa_auth->cb_ctx, drv_flags,
374 drv_flags2);
375}
376
377
378static bool wpa_auth_4way_handshake_offload(struct wpa_authenticator *wpa_auth)
379{
380 u64 drv_flags = 0, drv_flags2 = 0;
381
382 return wpa_auth_get_drv_flags(wpa_auth, &drv_flags, &drv_flags2) == 0 &&
383 (drv_flags2 & WPA_DRIVER_FLAGS2_4WAY_HANDSHAKE_AP_PSK);
384}
385
386
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700387int wpa_auth_for_each_sta(struct wpa_authenticator *wpa_auth,
388 int (*cb)(struct wpa_state_machine *sm, void *ctx),
389 void *cb_ctx)
390{
Hai Shalomfdcde762020-04-02 11:19:20 -0700391 if (!wpa_auth->cb->for_each_sta)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700392 return 0;
Paul Stewart092955c2017-02-06 09:13:09 -0800393 return wpa_auth->cb->for_each_sta(wpa_auth->cb_ctx, cb, cb_ctx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700394}
395
396
397int wpa_auth_for_each_auth(struct wpa_authenticator *wpa_auth,
398 int (*cb)(struct wpa_authenticator *a, void *ctx),
399 void *cb_ctx)
400{
Hai Shalomfdcde762020-04-02 11:19:20 -0700401 if (!wpa_auth->cb->for_each_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700402 return 0;
Paul Stewart092955c2017-02-06 09:13:09 -0800403 return wpa_auth->cb->for_each_auth(wpa_auth->cb_ctx, cb, cb_ctx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700404}
405
406
Hai Shalom60840252021-02-19 19:02:11 -0800407void wpa_auth_store_ptksa(struct wpa_authenticator *wpa_auth,
408 const u8 *addr, int cipher,
409 u32 life_time, const struct wpa_ptk *ptk)
410{
411 if (wpa_auth->cb->store_ptksa)
412 wpa_auth->cb->store_ptksa(wpa_auth->cb_ctx, addr, cipher,
413 life_time, ptk);
414}
415
416
Sunil Raviaf8751c2023-03-29 11:35:17 -0700417static void wpa_auth_remove_ptksa(struct wpa_authenticator *wpa_auth,
418 const u8 *addr, int cipher)
Hai Shalom60840252021-02-19 19:02:11 -0800419{
420 if (wpa_auth->cb->clear_ptksa)
421 wpa_auth->cb->clear_ptksa(wpa_auth->cb_ctx, addr, cipher);
422}
423
Sunil Raviaf8751c2023-03-29 11:35:17 -0700424
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700425void wpa_auth_logger(struct wpa_authenticator *wpa_auth, const u8 *addr,
426 logger_level level, const char *txt)
427{
Hai Shalomfdcde762020-04-02 11:19:20 -0700428 if (!wpa_auth->cb->logger)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700429 return;
Paul Stewart092955c2017-02-06 09:13:09 -0800430 wpa_auth->cb->logger(wpa_auth->cb_ctx, addr, level, txt);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700431}
432
433
434void wpa_auth_vlogger(struct wpa_authenticator *wpa_auth, const u8 *addr,
435 logger_level level, const char *fmt, ...)
436{
437 char *format;
438 int maxlen;
439 va_list ap;
440
Hai Shalomfdcde762020-04-02 11:19:20 -0700441 if (!wpa_auth->cb->logger)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700442 return;
443
444 maxlen = os_strlen(fmt) + 100;
445 format = os_malloc(maxlen);
446 if (!format)
447 return;
448
449 va_start(ap, fmt);
450 vsnprintf(format, maxlen, fmt, ap);
451 va_end(ap);
452
453 wpa_auth_logger(wpa_auth, addr, level, format);
454
455 os_free(format);
456}
457
458
459static void wpa_sta_disconnect(struct wpa_authenticator *wpa_auth,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700460 const u8 *addr, u16 reason)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700461{
Hai Shalomfdcde762020-04-02 11:19:20 -0700462 if (!wpa_auth->cb->disconnect)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700463 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700464 wpa_printf(MSG_DEBUG, "wpa_sta_disconnect STA " MACSTR " (reason %u)",
465 MAC2STR(addr), reason);
466 wpa_auth->cb->disconnect(wpa_auth->cb_ctx, addr, reason);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700467}
468
469
Hai Shalom74f70d42019-02-11 14:42:39 -0800470#ifdef CONFIG_OCV
471static int wpa_channel_info(struct wpa_authenticator *wpa_auth,
472 struct wpa_channel_info *ci)
473{
474 if (!wpa_auth->cb->channel_info)
475 return -1;
476 return wpa_auth->cb->channel_info(wpa_auth->cb_ctx, ci);
477}
478#endif /* CONFIG_OCV */
479
480
Hai Shalom021b0b52019-04-10 11:17:58 -0700481static int wpa_auth_update_vlan(struct wpa_authenticator *wpa_auth,
482 const u8 *addr, int vlan_id)
483{
484 if (!wpa_auth->cb->update_vlan)
485 return -1;
486 return wpa_auth->cb->update_vlan(wpa_auth->cb_ctx, addr, vlan_id);
487}
488
489
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700490static void wpa_rekey_gmk(void *eloop_ctx, void *timeout_ctx)
491{
492 struct wpa_authenticator *wpa_auth = eloop_ctx;
493
494 if (random_get_bytes(wpa_auth->group->GMK, WPA_GMK_LEN)) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700495 wpa_printf(MSG_ERROR,
496 "Failed to get random data for WPA initialization.");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700497 } else {
498 wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "GMK rekeyd");
499 wpa_hexdump_key(MSG_DEBUG, "GMK",
500 wpa_auth->group->GMK, WPA_GMK_LEN);
501 }
502
503 if (wpa_auth->conf.wpa_gmk_rekey) {
504 eloop_register_timeout(wpa_auth->conf.wpa_gmk_rekey, 0,
505 wpa_rekey_gmk, wpa_auth, NULL);
506 }
507}
508
509
Sunil Ravi7f769292024-07-23 22:21:32 +0000510static void wpa_rekey_all_groups(struct wpa_authenticator *wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700511{
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700512 struct wpa_group *group, *next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700513
514 wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "rekeying GTK");
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700515 group = wpa_auth->group;
516 while (group) {
Sunil Ravi7f769292024-07-23 22:21:32 +0000517 wpa_printf(MSG_DEBUG, "GTK rekey start for authenticator ("
518 MACSTR "), group vlan %d",
519 MAC2STR(wpa_auth->addr), group->vlan_id);
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700520 wpa_group_get(wpa_auth, group);
521
Hai Shalome21d4e82020-04-29 16:34:06 -0700522 group->GTKReKey = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700523 do {
Hai Shalome21d4e82020-04-29 16:34:06 -0700524 group->changed = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700525 wpa_group_sm_step(wpa_auth, group);
526 } while (group->changed);
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700527
528 next = group->next;
529 wpa_group_put(wpa_auth, group);
530 group = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700531 }
Sunil Ravi7f769292024-07-23 22:21:32 +0000532}
533
534
535#ifdef CONFIG_IEEE80211BE
536
537static void wpa_update_all_gtks(struct wpa_authenticator *wpa_auth)
538{
539 struct wpa_group *group, *next;
540
541 group = wpa_auth->group;
542 while (group) {
543 wpa_group_get(wpa_auth, group);
544
545 wpa_group_update_gtk(wpa_auth, group);
546 next = group->next;
547 wpa_group_put(wpa_auth, group);
548 group = next;
549 }
550}
551
552
553static int wpa_update_all_gtks_cb(struct wpa_authenticator *wpa_auth, void *ctx)
554{
555 const u8 *mld_addr = ctx;
556
557 if (!ether_addr_equal(wpa_auth->mld_addr, mld_addr))
558 return 0;
559
560 wpa_update_all_gtks(wpa_auth);
561 return 0;
562}
563
564
565static int wpa_rekey_all_groups_cb(struct wpa_authenticator *wpa_auth,
566 void *ctx)
567{
568 const u8 *mld_addr = ctx;
569
570 if (!ether_addr_equal(wpa_auth->mld_addr, mld_addr))
571 return 0;
572
573 wpa_rekey_all_groups(wpa_auth);
574 return 0;
575}
576
577#endif /* CONFIG_IEEE80211BE */
578
579
580static void wpa_rekey_gtk(void *eloop_ctx, void *timeout_ctx)
581{
582 struct wpa_authenticator *wpa_auth = eloop_ctx;
583
584#ifdef CONFIG_IEEE80211BE
585 if (wpa_auth->is_ml) {
586 /* Non-primary ML authenticator eloop timer for group rekey is
587 * never started and shouldn't fire. Check and warn just in
588 * case. */
589 if (!wpa_auth->primary_auth) {
590 wpa_printf(MSG_DEBUG,
591 "RSN: Cannot start GTK rekey on non-primary ML authenticator");
592 return;
593 }
594
595 /* Generate all the new group keys */
596 wpa_auth_for_each_auth(wpa_auth, wpa_update_all_gtks_cb,
597 wpa_auth->mld_addr);
598
599 /* Send all the generated group keys to the respective stations
600 * with group key handshake. */
601 wpa_auth_for_each_auth(wpa_auth, wpa_rekey_all_groups_cb,
602 wpa_auth->mld_addr);
603 } else {
604 wpa_rekey_all_groups(wpa_auth);
605 }
606#else /* CONFIG_IEEE80211BE */
607 wpa_rekey_all_groups(wpa_auth);
608#endif /* CONFIG_IEEE80211BE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700609
610 if (wpa_auth->conf.wpa_group_rekey) {
611 eloop_register_timeout(wpa_auth->conf.wpa_group_rekey,
612 0, wpa_rekey_gtk, wpa_auth, NULL);
613 }
614}
615
616
617static void wpa_rekey_ptk(void *eloop_ctx, void *timeout_ctx)
618{
619 struct wpa_authenticator *wpa_auth = eloop_ctx;
620 struct wpa_state_machine *sm = timeout_ctx;
621
Sunil Raviaf8751c2023-03-29 11:35:17 -0700622 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
623 "rekeying PTK");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700624 wpa_request_new_ptk(sm);
625 wpa_sm_step(sm);
626}
627
628
Hai Shalom81f62d82019-07-22 12:10:00 -0700629void wpa_auth_set_ptk_rekey_timer(struct wpa_state_machine *sm)
630{
631 if (sm && sm->wpa_auth->conf.wpa_ptk_rekey) {
632 wpa_printf(MSG_DEBUG, "WPA: Start PTK rekeying timer for "
Sunil Raviaf8751c2023-03-29 11:35:17 -0700633 MACSTR " (%d seconds)",
634 MAC2STR(wpa_auth_get_spa(sm)),
Hai Shalom81f62d82019-07-22 12:10:00 -0700635 sm->wpa_auth->conf.wpa_ptk_rekey);
636 eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm);
637 eloop_register_timeout(sm->wpa_auth->conf.wpa_ptk_rekey, 0,
638 wpa_rekey_ptk, sm->wpa_auth, sm);
639 }
640}
641
642
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700643static int wpa_auth_pmksa_clear_cb(struct wpa_state_machine *sm, void *ctx)
644{
645 if (sm->pmksa == ctx)
646 sm->pmksa = NULL;
647 return 0;
648}
649
650
651static void wpa_auth_pmksa_free_cb(struct rsn_pmksa_cache_entry *entry,
652 void *ctx)
653{
654 struct wpa_authenticator *wpa_auth = ctx;
655 wpa_auth_for_each_sta(wpa_auth, wpa_auth_pmksa_clear_cb, entry);
656}
657
658
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700659static int wpa_group_init_gmk_and_counter(struct wpa_authenticator *wpa_auth,
660 struct wpa_group *group)
661{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800662 u8 buf[ETH_ALEN + 8 + sizeof(unsigned long)];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700663 u8 rkey[32];
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800664 unsigned long ptr;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700665
666 if (random_get_bytes(group->GMK, WPA_GMK_LEN) < 0)
667 return -1;
668 wpa_hexdump_key(MSG_DEBUG, "GMK", group->GMK, WPA_GMK_LEN);
669
670 /*
671 * Counter = PRF-256(Random number, "Init Counter",
672 * Local MAC Address || Time)
673 */
674 os_memcpy(buf, wpa_auth->addr, ETH_ALEN);
675 wpa_get_ntp_timestamp(buf + ETH_ALEN);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800676 ptr = (unsigned long) group;
677 os_memcpy(buf + ETH_ALEN + 8, &ptr, sizeof(ptr));
Hai Shalom74f70d42019-02-11 14:42:39 -0800678#ifdef TEST_FUZZ
679 os_memset(buf + ETH_ALEN, 0xab, 8);
680 os_memset(buf + ETH_ALEN + 8, 0xcd, sizeof(ptr));
681#endif /* TEST_FUZZ */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700682 if (random_get_bytes(rkey, sizeof(rkey)) < 0)
683 return -1;
684
685 if (sha1_prf(rkey, sizeof(rkey), "Init Counter", buf, sizeof(buf),
686 group->Counter, WPA_NONCE_LEN) < 0)
687 return -1;
688 wpa_hexdump_key(MSG_DEBUG, "Key Counter",
689 group->Counter, WPA_NONCE_LEN);
690
691 return 0;
692}
693
694
695static struct wpa_group * wpa_group_init(struct wpa_authenticator *wpa_auth,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800696 int vlan_id, int delay_init)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700697{
698 struct wpa_group *group;
699
700 group = os_zalloc(sizeof(struct wpa_group));
Hai Shalomfdcde762020-04-02 11:19:20 -0700701 if (!group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700702 return NULL;
703
Hai Shalome21d4e82020-04-29 16:34:06 -0700704 group->GTKAuthenticator = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700705 group->vlan_id = vlan_id;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -0700706 group->GTK_len = wpa_cipher_key_len(wpa_auth->conf.wpa_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700707
708 if (random_pool_ready() != 1) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700709 wpa_printf(MSG_INFO,
710 "WPA: Not enough entropy in random pool for secure operations - update keys later when the first station connects");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700711 }
712
713 /*
714 * Set initial GMK/Counter value here. The actual values that will be
715 * used in negotiations will be set once the first station tries to
716 * connect. This allows more time for collecting additional randomness
717 * on embedded devices.
718 */
719 if (wpa_group_init_gmk_and_counter(wpa_auth, group) < 0) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700720 wpa_printf(MSG_ERROR,
721 "Failed to get random data for WPA initialization.");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700722 os_free(group);
723 return NULL;
724 }
725
Hai Shalome21d4e82020-04-29 16:34:06 -0700726 group->GInit = true;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800727 if (delay_init) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700728 wpa_printf(MSG_DEBUG,
729 "WPA: Delay group state machine start until Beacon frames have been configured");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800730 /* Initialization is completed in wpa_init_keys(). */
731 } else {
732 wpa_group_sm_step(wpa_auth, group);
Hai Shalome21d4e82020-04-29 16:34:06 -0700733 group->GInit = false;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800734 wpa_group_sm_step(wpa_auth, group);
735 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700736
737 return group;
738}
739
740
741/**
742 * wpa_init - Initialize WPA authenticator
743 * @addr: Authenticator address
744 * @conf: Configuration for WPA authenticator
745 * @cb: Callback functions for WPA authenticator
746 * Returns: Pointer to WPA authenticator data or %NULL on failure
747 */
748struct wpa_authenticator * wpa_init(const u8 *addr,
749 struct wpa_auth_config *conf,
Paul Stewart092955c2017-02-06 09:13:09 -0800750 const struct wpa_auth_callbacks *cb,
751 void *cb_ctx)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700752{
753 struct wpa_authenticator *wpa_auth;
754
755 wpa_auth = os_zalloc(sizeof(struct wpa_authenticator));
Hai Shalomfdcde762020-04-02 11:19:20 -0700756 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700757 return NULL;
Sunil Ravi7f769292024-07-23 22:21:32 +0000758
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700759 os_memcpy(wpa_auth->addr, addr, ETH_ALEN);
760 os_memcpy(&wpa_auth->conf, conf, sizeof(*conf));
Sunil Ravi7f769292024-07-23 22:21:32 +0000761
762#ifdef CONFIG_IEEE80211BE
763 if (conf->mld_addr) {
764 wpa_auth->is_ml = true;
765 wpa_auth->link_id = conf->link_id;
766 wpa_auth->primary_auth = !conf->first_link_auth;
767 os_memcpy(wpa_auth->mld_addr, conf->mld_addr, ETH_ALEN);
768 }
769#endif /* CONFIG_IEEE80211BE */
770
Paul Stewart092955c2017-02-06 09:13:09 -0800771 wpa_auth->cb = cb;
772 wpa_auth->cb_ctx = cb_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700773
774 if (wpa_auth_gen_wpa_ie(wpa_auth)) {
775 wpa_printf(MSG_ERROR, "Could not generate WPA IE.");
776 os_free(wpa_auth);
777 return NULL;
778 }
779
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800780 wpa_auth->group = wpa_group_init(wpa_auth, 0, 1);
Hai Shalomfdcde762020-04-02 11:19:20 -0700781 if (!wpa_auth->group) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700782 os_free(wpa_auth->wpa_ie);
783 os_free(wpa_auth);
784 return NULL;
785 }
786
787 wpa_auth->pmksa = pmksa_cache_auth_init(wpa_auth_pmksa_free_cb,
788 wpa_auth);
Hai Shalomfdcde762020-04-02 11:19:20 -0700789 if (!wpa_auth->pmksa) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700790 wpa_printf(MSG_ERROR, "PMKSA cache initialization failed.");
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800791 os_free(wpa_auth->group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700792 os_free(wpa_auth->wpa_ie);
793 os_free(wpa_auth);
794 return NULL;
795 }
796
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800797#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700798 wpa_auth->ft_pmk_cache = wpa_ft_pmk_cache_init();
Hai Shalomfdcde762020-04-02 11:19:20 -0700799 if (!wpa_auth->ft_pmk_cache) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700800 wpa_printf(MSG_ERROR, "FT PMK cache initialization failed.");
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800801 os_free(wpa_auth->group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700802 os_free(wpa_auth->wpa_ie);
803 pmksa_cache_auth_deinit(wpa_auth->pmksa);
804 os_free(wpa_auth);
805 return NULL;
806 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800807#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700808
809 if (wpa_auth->conf.wpa_gmk_rekey) {
810 eloop_register_timeout(wpa_auth->conf.wpa_gmk_rekey, 0,
811 wpa_rekey_gmk, wpa_auth, NULL);
812 }
813
Sunil Ravi7f769292024-07-23 22:21:32 +0000814#ifdef CONFIG_IEEE80211BE
815 /* For AP MLD, run group rekey timer only on one link (first) and
816 * whenever it fires do rekey on all associated ML links in one shot.
817 */
818 if ((!wpa_auth->is_ml || !conf->first_link_auth) &&
819 wpa_auth->conf.wpa_group_rekey) {
820#else /* CONFIG_IEEE80211BE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700821 if (wpa_auth->conf.wpa_group_rekey) {
Sunil Ravi7f769292024-07-23 22:21:32 +0000822#endif /* CONFIG_IEEE80211BE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700823 eloop_register_timeout(wpa_auth->conf.wpa_group_rekey, 0,
824 wpa_rekey_gtk, wpa_auth, NULL);
825 }
826
Dmitry Shmidtcf32e602014-01-28 10:57:39 -0800827#ifdef CONFIG_P2P
828 if (WPA_GET_BE32(conf->ip_addr_start)) {
829 int count = WPA_GET_BE32(conf->ip_addr_end) -
830 WPA_GET_BE32(conf->ip_addr_start) + 1;
831 if (count > 1000)
832 count = 1000;
833 if (count > 0)
834 wpa_auth->ip_pool = bitfield_alloc(count);
835 }
836#endif /* CONFIG_P2P */
837
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000838 if (conf->tx_bss_auth && conf->beacon_prot) {
839 conf->tx_bss_auth->non_tx_beacon_prot = true;
840 if (!conf->tx_bss_auth->conf.beacon_prot)
841 conf->tx_bss_auth->conf.beacon_prot = true;
842 if (!conf->tx_bss_auth->conf.group_mgmt_cipher)
843 conf->tx_bss_auth->conf.group_mgmt_cipher =
844 conf->group_mgmt_cipher;
845 }
846
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700847 return wpa_auth;
848}
849
850
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800851int wpa_init_keys(struct wpa_authenticator *wpa_auth)
852{
853 struct wpa_group *group = wpa_auth->group;
854
Hai Shalomfdcde762020-04-02 11:19:20 -0700855 wpa_printf(MSG_DEBUG,
856 "WPA: Start group state machine to set initial keys");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800857 wpa_group_sm_step(wpa_auth, group);
Hai Shalome21d4e82020-04-29 16:34:06 -0700858 group->GInit = false;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800859 wpa_group_sm_step(wpa_auth, group);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800860 if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
861 return -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800862 return 0;
863}
864
865
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000866static void wpa_auth_free_conf(struct wpa_auth_config *conf)
867{
868#ifdef CONFIG_TESTING_OPTIONS
869 wpabuf_free(conf->eapol_m1_elements);
870 conf->eapol_m1_elements = NULL;
871 wpabuf_free(conf->eapol_m3_elements);
872 conf->eapol_m3_elements = NULL;
873#endif /* CONFIG_TESTING_OPTIONS */
874}
875
876
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700877/**
878 * wpa_deinit - Deinitialize WPA authenticator
879 * @wpa_auth: Pointer to WPA authenticator data from wpa_init()
880 */
881void wpa_deinit(struct wpa_authenticator *wpa_auth)
882{
883 struct wpa_group *group, *prev;
884
885 eloop_cancel_timeout(wpa_rekey_gmk, wpa_auth, NULL);
Sunil Ravi7f769292024-07-23 22:21:32 +0000886
887 /* TODO: Assign ML primary authenticator to next link authenticator and
888 * start rekey timer. */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700889 eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL);
890
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700891 pmksa_cache_auth_deinit(wpa_auth->pmksa);
892
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800893#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700894 wpa_ft_pmk_cache_deinit(wpa_auth->ft_pmk_cache);
895 wpa_auth->ft_pmk_cache = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700896 wpa_ft_deinit(wpa_auth);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800897#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700898
Dmitry Shmidtcf32e602014-01-28 10:57:39 -0800899#ifdef CONFIG_P2P
900 bitfield_free(wpa_auth->ip_pool);
901#endif /* CONFIG_P2P */
902
903
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700904 os_free(wpa_auth->wpa_ie);
905
906 group = wpa_auth->group;
907 while (group) {
908 prev = group;
909 group = group->next;
Sunil Ravia04bd252022-05-02 22:54:18 -0700910 bin_clear_free(prev, sizeof(*prev));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700911 }
912
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000913 wpa_auth_free_conf(&wpa_auth->conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700914 os_free(wpa_auth);
915}
916
917
918/**
919 * wpa_reconfig - Update WPA authenticator configuration
920 * @wpa_auth: Pointer to WPA authenticator data from wpa_init()
921 * @conf: Configuration for WPA authenticator
922 */
923int wpa_reconfig(struct wpa_authenticator *wpa_auth,
924 struct wpa_auth_config *conf)
925{
926 struct wpa_group *group;
Hai Shalomfdcde762020-04-02 11:19:20 -0700927
928 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700929 return 0;
930
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000931 wpa_auth_free_conf(&wpa_auth->conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700932 os_memcpy(&wpa_auth->conf, conf, sizeof(*conf));
933 if (wpa_auth_gen_wpa_ie(wpa_auth)) {
934 wpa_printf(MSG_ERROR, "Could not generate WPA IE.");
935 return -1;
936 }
937
938 /*
939 * Reinitialize GTK to make sure it is suitable for the new
940 * configuration.
941 */
942 group = wpa_auth->group;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -0700943 group->GTK_len = wpa_cipher_key_len(wpa_auth->conf.wpa_group);
Hai Shalome21d4e82020-04-29 16:34:06 -0700944 group->GInit = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700945 wpa_group_sm_step(wpa_auth, group);
Hai Shalome21d4e82020-04-29 16:34:06 -0700946 group->GInit = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700947 wpa_group_sm_step(wpa_auth, group);
948
949 return 0;
950}
951
952
953struct wpa_state_machine *
Dmitry Shmidt391c59f2013-09-03 12:16:28 -0700954wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr,
955 const u8 *p2p_dev_addr)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700956{
957 struct wpa_state_machine *sm;
958
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800959 if (wpa_auth->group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
960 return NULL;
961
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700962 sm = os_zalloc(sizeof(struct wpa_state_machine));
Hai Shalomfdcde762020-04-02 11:19:20 -0700963 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700964 return NULL;
965 os_memcpy(sm->addr, addr, ETH_ALEN);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -0700966 if (p2p_dev_addr)
967 os_memcpy(sm->p2p_dev_addr, p2p_dev_addr, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700968
969 sm->wpa_auth = wpa_auth;
970 sm->group = wpa_auth->group;
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700971 wpa_group_get(sm->wpa_auth, sm->group);
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000972#ifdef CONFIG_IEEE80211BE
973 sm->mld_assoc_link_id = -1;
974#endif /* CONFIG_IEEE80211BE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700975
976 return sm;
977}
978
979
980int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth,
981 struct wpa_state_machine *sm)
982{
Hai Shalomfdcde762020-04-02 11:19:20 -0700983 if (!wpa_auth || !wpa_auth->conf.wpa || !sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700984 return -1;
985
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800986#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700987 if (sm->ft_completed) {
Sunil Raviaf8751c2023-03-29 11:35:17 -0700988 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -0700989 "FT authentication already completed - do not start 4-way handshake");
Dmitry Shmidt71757432014-06-02 13:50:35 -0700990 /* Go to PTKINITDONE state to allow GTK rekeying */
991 sm->wpa_ptk_state = WPA_PTK_PTKINITDONE;
Hai Shalome21d4e82020-04-29 16:34:06 -0700992 sm->Pair = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700993 return 0;
994 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800995#endif /* CONFIG_IEEE80211R_AP */
996
997#ifdef CONFIG_FILS
998 if (sm->fils_completed) {
Sunil Raviaf8751c2023-03-29 11:35:17 -0700999 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001000 "FILS authentication already completed - do not start 4-way handshake");
1001 /* Go to PTKINITDONE state to allow GTK rekeying */
1002 sm->wpa_ptk_state = WPA_PTK_PTKINITDONE;
Hai Shalome21d4e82020-04-29 16:34:06 -07001003 sm->Pair = true;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001004 return 0;
1005 }
1006#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001007
1008 if (sm->started) {
1009 os_memset(&sm->key_replay, 0, sizeof(sm->key_replay));
Hai Shalome21d4e82020-04-29 16:34:06 -07001010 sm->ReAuthenticationRequest = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001011 return wpa_sm_step(sm);
1012 }
1013
Sunil Raviaf8751c2023-03-29 11:35:17 -07001014 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001015 "start authentication");
1016 sm->started = 1;
1017
Hai Shalome21d4e82020-04-29 16:34:06 -07001018 sm->Init = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001019 if (wpa_sm_step(sm) == 1)
1020 return 1; /* should not really happen */
Hai Shalome21d4e82020-04-29 16:34:06 -07001021 sm->Init = false;
Sunil Ravi79e6c4f2025-01-04 00:47:06 +00001022
1023 if (wpa_auth_4way_handshake_offload(sm->wpa_auth))
1024 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
1025 "Skip EAPOL for 4-way handshake offload case");
1026 else
1027 sm->AuthenticationRequest = true;
1028
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001029 return wpa_sm_step(sm);
1030}
1031
1032
1033void wpa_auth_sta_no_wpa(struct wpa_state_machine *sm)
1034{
1035 /* WPA/RSN was not used - clear WPA state. This is needed if the STA
1036 * reassociates back to the same AP while the previous entry for the
1037 * STA has not yet been removed. */
Hai Shalomfdcde762020-04-02 11:19:20 -07001038 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001039 return;
1040
1041 sm->wpa_key_mgmt = 0;
1042}
1043
1044
1045static void wpa_free_sta_sm(struct wpa_state_machine *sm)
1046{
Sunil Ravi7f769292024-07-23 22:21:32 +00001047#ifdef CONFIG_IEEE80211BE
1048 int link_id;
1049#endif /* CONFIG_IEEE80211BE */
1050
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001051#ifdef CONFIG_P2P
1052 if (WPA_GET_BE32(sm->ip_addr)) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001053 wpa_printf(MSG_DEBUG,
1054 "P2P: Free assigned IP address %u.%u.%u.%u from "
Sunil8cd6f4d2022-06-28 18:40:46 +00001055 MACSTR " (bit %u)",
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001056 sm->ip_addr[0], sm->ip_addr[1],
1057 sm->ip_addr[2], sm->ip_addr[3],
Sunil Raviaf8751c2023-03-29 11:35:17 -07001058 MAC2STR(wpa_auth_get_spa(sm)),
1059 sm->ip_addr_bit);
Sunil8cd6f4d2022-06-28 18:40:46 +00001060 bitfield_clear(sm->wpa_auth->ip_pool, sm->ip_addr_bit);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001061 }
1062#endif /* CONFIG_P2P */
Sunil Ravi7f769292024-07-23 22:21:32 +00001063 if (sm->GUpdateStationKeys)
1064 wpa_gkeydone_sta(sm);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001065#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001066 os_free(sm->assoc_resp_ftie);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07001067 wpabuf_free(sm->ft_pending_req_ies);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001068#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001069 os_free(sm->last_rx_eapol_key);
1070 os_free(sm->wpa_ie);
Hai Shalomc3565922019-10-28 11:58:20 -07001071 os_free(sm->rsnxe);
Sunil Ravic0f5d412024-09-11 22:12:49 +00001072 os_free(sm->rsn_selection);
Sunil Ravi7f769292024-07-23 22:21:32 +00001073#ifdef CONFIG_IEEE80211BE
Sunil Ravi79e6c4f2025-01-04 00:47:06 +00001074 for_each_sm_auth(sm, link_id)
Sunil Ravi7f769292024-07-23 22:21:32 +00001075 sm->mld_links[link_id].wpa_auth = NULL;
Sunil Ravi7f769292024-07-23 22:21:32 +00001076#endif /* CONFIG_IEEE80211BE */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07001077 wpa_group_put(sm->wpa_auth, sm->group);
Hai Shalom021b0b52019-04-10 11:17:58 -07001078#ifdef CONFIG_DPP2
1079 wpabuf_clear_free(sm->dpp_z);
1080#endif /* CONFIG_DPP2 */
Hai Shalom1dc4d202019-04-29 16:22:27 -07001081 bin_clear_free(sm, sizeof(*sm));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001082}
1083
1084
1085void wpa_auth_sta_deinit(struct wpa_state_machine *sm)
1086{
Hai Shalomfdcde762020-04-02 11:19:20 -07001087 struct wpa_authenticator *wpa_auth;
1088
1089 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001090 return;
1091
Hai Shalomfdcde762020-04-02 11:19:20 -07001092 wpa_auth = sm->wpa_auth;
1093 if (wpa_auth->conf.wpa_strict_rekey && sm->has_GTK) {
Sunil Ravi7f769292024-07-23 22:21:32 +00001094 struct wpa_authenticator *primary_auth = wpa_auth;
1095
Sunil Raviaf8751c2023-03-29 11:35:17 -07001096 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07001097 "strict rekeying - force GTK rekey since STA is leaving");
Sunil Ravi7f769292024-07-23 22:21:32 +00001098
1099#ifdef CONFIG_IEEE80211BE
1100 if (wpa_auth->is_ml && !wpa_auth->primary_auth)
1101 primary_auth = wpa_get_primary_auth(wpa_auth);
1102#endif /* CONFIG_IEEE80211BE */
1103
Roshan Pius3a1667e2018-07-03 15:17:14 -07001104 if (eloop_deplete_timeout(0, 500000, wpa_rekey_gtk,
Sunil Ravi7f769292024-07-23 22:21:32 +00001105 primary_auth, NULL) == -1)
Hai Shalomfdcde762020-04-02 11:19:20 -07001106 eloop_register_timeout(0, 500000, wpa_rekey_gtk,
Sunil Ravi7f769292024-07-23 22:21:32 +00001107 primary_auth, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001108 }
1109
Hai Shalomfdcde762020-04-02 11:19:20 -07001110 eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001111 sm->pending_1_of_4_timeout = 0;
1112 eloop_cancel_timeout(wpa_sm_call_step, sm, NULL);
Hai Shalomfdcde762020-04-02 11:19:20 -07001113 eloop_cancel_timeout(wpa_rekey_ptk, wpa_auth, sm);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001114#ifdef CONFIG_IEEE80211R_AP
1115 wpa_ft_sta_deinit(sm);
1116#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001117 if (sm->in_step_loop) {
1118 /* Must not free state machine while wpa_sm_step() is running.
1119 * Freeing will be completed in the end of wpa_sm_step(). */
Hai Shalomfdcde762020-04-02 11:19:20 -07001120 wpa_printf(MSG_DEBUG,
1121 "WPA: Registering pending STA state machine deinit for "
Sunil Raviaf8751c2023-03-29 11:35:17 -07001122 MACSTR, MAC2STR(wpa_auth_get_spa(sm)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001123 sm->pending_deinit = 1;
1124 } else
1125 wpa_free_sta_sm(sm);
1126}
1127
1128
1129static void wpa_request_new_ptk(struct wpa_state_machine *sm)
1130{
Hai Shalomfdcde762020-04-02 11:19:20 -07001131 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001132 return;
1133
Hai Shalomfdcde762020-04-02 11:19:20 -07001134 if (!sm->use_ext_key_id && sm->wpa_auth->conf.wpa_deny_ptk0_rekey) {
1135 wpa_printf(MSG_INFO,
1136 "WPA: PTK0 rekey not allowed, disconnect " MACSTR,
Sunil Raviaf8751c2023-03-29 11:35:17 -07001137 MAC2STR(wpa_auth_get_spa(sm)));
Hai Shalome21d4e82020-04-29 16:34:06 -07001138 sm->Disconnect = true;
Hai Shalomfdcde762020-04-02 11:19:20 -07001139 /* Try to encourage the STA to reconnect */
1140 sm->disconnect_reason =
1141 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA;
1142 } else {
1143 if (sm->use_ext_key_id)
1144 sm->keyidx_active ^= 1; /* flip Key ID */
Hai Shalome21d4e82020-04-29 16:34:06 -07001145 sm->PTKRequest = true;
Hai Shalomfdcde762020-04-02 11:19:20 -07001146 sm->PTK_valid = 0;
1147 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001148}
1149
1150
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001151static int wpa_replay_counter_valid(struct wpa_key_replay_counter *ctr,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001152 const u8 *replay_counter)
1153{
1154 int i;
1155 for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001156 if (!ctr[i].valid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001157 break;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001158 if (os_memcmp(replay_counter, ctr[i].counter,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001159 WPA_REPLAY_COUNTER_LEN) == 0)
1160 return 1;
1161 }
1162 return 0;
1163}
1164
1165
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001166static void wpa_replay_counter_mark_invalid(struct wpa_key_replay_counter *ctr,
1167 const u8 *replay_counter)
1168{
1169 int i;
1170 for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) {
1171 if (ctr[i].valid &&
Hai Shalomfdcde762020-04-02 11:19:20 -07001172 (!replay_counter ||
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001173 os_memcmp(replay_counter, ctr[i].counter,
1174 WPA_REPLAY_COUNTER_LEN) == 0))
Hai Shalome21d4e82020-04-29 16:34:06 -07001175 ctr[i].valid = false;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001176 }
1177}
1178
1179
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001180#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001181static int ft_check_msg_2_of_4(struct wpa_authenticator *wpa_auth,
1182 struct wpa_state_machine *sm,
1183 struct wpa_eapol_ie_parse *kde)
1184{
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001185 struct wpa_ie_data ie, assoc_ie;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001186 struct rsn_mdie *mdie;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001187 unsigned int i, j;
1188 bool found = false;
1189
1190 /* Verify that PMKR1Name from EAPOL-Key message 2/4 matches the value
1191 * we derived. */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001192
1193 if (wpa_parse_wpa_ie_rsn(kde->rsn_ie, kde->rsn_ie_len, &ie) < 0 ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001194 ie.num_pmkid < 1 || !ie.pmkid) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001195 wpa_printf(MSG_DEBUG,
1196 "FT: No PMKR1Name in FT 4-way handshake message 2/4");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001197 return -1;
1198 }
1199
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001200 if (wpa_parse_wpa_ie_rsn(sm->wpa_ie, sm->wpa_ie_len, &assoc_ie) < 0) {
1201 wpa_printf(MSG_DEBUG,
1202 "FT: Could not parse (Re)Association Request frame RSNE");
1203 os_memset(&assoc_ie, 0, sizeof(assoc_ie));
1204 /* Continue to allow PMKR1Name matching to be done to cover the
1205 * case where it is the only listed PMKID. */
1206 }
1207
1208 for (i = 0; i < ie.num_pmkid; i++) {
1209 const u8 *pmkid = ie.pmkid + i * PMKID_LEN;
1210
1211 if (os_memcmp_const(pmkid, sm->pmk_r1_name,
1212 WPA_PMK_NAME_LEN) == 0) {
1213 wpa_printf(MSG_DEBUG,
1214 "FT: RSNE[PMKID[%u]] from supplicant matches PMKR1Name",
1215 i);
1216 found = true;
1217 } else {
1218 for (j = 0; j < assoc_ie.num_pmkid; j++) {
1219 if (os_memcmp(pmkid,
1220 assoc_ie.pmkid + j * PMKID_LEN,
1221 PMKID_LEN) == 0)
1222 break;
1223 }
1224
1225 if (j == assoc_ie.num_pmkid) {
1226 wpa_printf(MSG_DEBUG,
1227 "FT: RSNE[PMKID[%u]] from supplicant is neither PMKR1Name nor included in AssocReq",
1228 i);
1229 found = false;
1230 break;
1231 }
1232 wpa_printf(MSG_DEBUG,
1233 "FT: RSNE[PMKID[%u]] from supplicant is not PMKR1Name, but matches a PMKID in AssocReq",
1234 i);
1235 }
1236 }
1237
1238 if (!found) {
1239 wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm),
1240 LOGGER_DEBUG,
1241 "PMKR1Name mismatch in FT 4-way handshake");
1242 wpa_hexdump(MSG_DEBUG,
1243 "FT: PMKIDs/PMKR1Name from Supplicant",
1244 ie.pmkid, ie.num_pmkid * PMKID_LEN);
1245 wpa_hexdump(MSG_DEBUG, "FT: Derived PMKR1Name",
1246 sm->pmk_r1_name, WPA_PMK_NAME_LEN);
1247 return -1;
1248 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001249
1250 if (!kde->mdie || !kde->ftie) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001251 wpa_printf(MSG_DEBUG,
1252 "FT: No %s in FT 4-way handshake message 2/4",
1253 kde->mdie ? "FTIE" : "MDIE");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001254 return -1;
1255 }
1256
1257 mdie = (struct rsn_mdie *) (kde->mdie + 2);
1258 if (kde->mdie[1] < sizeof(struct rsn_mdie) ||
1259 os_memcmp(wpa_auth->conf.mobility_domain, mdie->mobility_domain,
1260 MOBILITY_DOMAIN_ID_LEN) != 0) {
1261 wpa_printf(MSG_DEBUG, "FT: MDIE mismatch");
1262 return -1;
1263 }
1264
1265 if (sm->assoc_resp_ftie &&
1266 (kde->ftie[1] != sm->assoc_resp_ftie[1] ||
1267 os_memcmp(kde->ftie, sm->assoc_resp_ftie,
1268 2 + sm->assoc_resp_ftie[1]) != 0)) {
1269 wpa_printf(MSG_DEBUG, "FT: FTIE mismatch");
1270 wpa_hexdump(MSG_DEBUG, "FT: FTIE in EAPOL-Key msg 2/4",
1271 kde->ftie, kde->ftie_len);
1272 wpa_hexdump(MSG_DEBUG, "FT: FTIE in (Re)AssocResp",
1273 sm->assoc_resp_ftie, 2 + sm->assoc_resp_ftie[1]);
1274 return -1;
1275 }
1276
1277 return 0;
1278}
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001279#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001280
1281
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001282static int wpa_receive_error_report(struct wpa_authenticator *wpa_auth,
1283 struct wpa_state_machine *sm, int group)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001284{
1285 /* Supplicant reported a Michael MIC error */
Sunil Raviaf8751c2023-03-29 11:35:17 -07001286 wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001287 "received EAPOL-Key Error Request (STA detected Michael MIC failure (group=%d))",
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001288 group);
1289
1290 if (group && wpa_auth->conf.wpa_group != WPA_CIPHER_TKIP) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07001291 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001292 "ignore Michael MIC failure report since group cipher is not TKIP");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001293 } else if (!group && sm->pairwise != WPA_CIPHER_TKIP) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07001294 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001295 "ignore Michael MIC failure report since pairwise cipher is not TKIP");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001296 } else {
Sunil Raviaf8751c2023-03-29 11:35:17 -07001297 if (wpa_auth_mic_failure_report(wpa_auth,
1298 wpa_auth_get_spa(sm)) > 0)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001299 return 1; /* STA entry was removed */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001300 sm->dot11RSNAStatsTKIPRemoteMICFailures++;
1301 wpa_auth->dot11RSNAStatsTKIPRemoteMICFailures++;
1302 }
1303
1304 /*
1305 * Error report is not a request for a new key handshake, but since
1306 * Authenticator may do it, let's change the keys now anyway.
1307 */
1308 wpa_request_new_ptk(sm);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001309 return 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001310}
1311
1312
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001313static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data,
1314 size_t data_len)
1315{
1316 struct wpa_ptk PTK;
1317 int ok = 0;
1318 const u8 *pmk = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001319 size_t pmk_len;
Hai Shalom021b0b52019-04-10 11:17:58 -07001320 int vlan_id = 0;
Sunil Raviaf8751c2023-03-29 11:35:17 -07001321 u8 pmk_r0[PMK_LEN_MAX], pmk_r0_name[WPA_PMK_NAME_LEN];
1322 u8 pmk_r1[PMK_LEN_MAX];
1323 size_t key_len;
1324 int ret = -1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001325
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001326 os_memset(&PTK, 0, sizeof(PTK));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001327 for (;;) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001328 if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
1329 !wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001330 pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr,
Hai Shalom021b0b52019-04-10 11:17:58 -07001331 sm->p2p_dev_addr, pmk, &pmk_len,
1332 &vlan_id);
Hai Shalomfdcde762020-04-02 11:19:20 -07001333 if (!pmk)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001334 break;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001335#ifdef CONFIG_IEEE80211R_AP
1336 if (wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) {
1337 os_memcpy(sm->xxkey, pmk, pmk_len);
1338 sm->xxkey_len = pmk_len;
1339 }
1340#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001341 } else {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001342 pmk = sm->PMK;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001343 pmk_len = sm->pmk_len;
1344 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001345
Sunil Raviaf8751c2023-03-29 11:35:17 -07001346 if (wpa_derive_ptk(sm, sm->alt_SNonce, pmk, pmk_len, &PTK, 0,
Sunil Ravi7f769292024-07-23 22:21:32 +00001347 pmk_r0, pmk_r1, pmk_r0_name, &key_len,
1348 false) < 0)
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001349 break;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001350
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001351 if (wpa_verify_key_mic(sm->wpa_key_mgmt, pmk_len, &PTK,
1352 data, data_len) == 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001353 if (sm->PMK != pmk) {
1354 os_memcpy(sm->PMK, pmk, pmk_len);
1355 sm->pmk_len = pmk_len;
1356 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001357 ok = 1;
1358 break;
1359 }
1360
Roshan Pius3a1667e2018-07-03 15:17:14 -07001361 if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
1362 wpa_key_mgmt_sae(sm->wpa_key_mgmt))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001363 break;
1364 }
1365
1366 if (!ok) {
1367 wpa_printf(MSG_DEBUG,
1368 "WPA: Earlier SNonce did not result in matching MIC");
Sunil Raviaf8751c2023-03-29 11:35:17 -07001369 goto fail;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001370 }
1371
1372 wpa_printf(MSG_DEBUG,
1373 "WPA: Earlier SNonce resulted in matching MIC");
1374 sm->alt_snonce_valid = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -07001375
1376 if (vlan_id && wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
1377 wpa_auth_update_vlan(sm->wpa_auth, sm->addr, vlan_id) < 0)
Sunil Raviaf8751c2023-03-29 11:35:17 -07001378 goto fail;
1379
1380#ifdef CONFIG_IEEE80211R_AP
1381 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt) && !sm->ft_completed) {
1382 wpa_printf(MSG_DEBUG, "FT: Store PMK-R0/PMK-R1");
1383 wpa_auth_ft_store_keys(sm, pmk_r0, pmk_r1, pmk_r0_name,
1384 key_len);
1385 }
1386#endif /* CONFIG_IEEE80211R_AP */
Hai Shalom021b0b52019-04-10 11:17:58 -07001387
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001388 os_memcpy(sm->SNonce, sm->alt_SNonce, WPA_NONCE_LEN);
1389 os_memcpy(&sm->PTK, &PTK, sizeof(PTK));
Hai Shalom81f62d82019-07-22 12:10:00 -07001390 forced_memzero(&PTK, sizeof(PTK));
Hai Shalome21d4e82020-04-29 16:34:06 -07001391 sm->PTK_valid = true;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001392
Sunil Raviaf8751c2023-03-29 11:35:17 -07001393 ret = 0;
1394fail:
1395 forced_memzero(pmk_r0, sizeof(pmk_r0));
1396 forced_memzero(pmk_r1, sizeof(pmk_r1));
1397 return ret;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001398}
1399
1400
Hai Shaloma20dcd72022-02-04 13:43:00 -08001401static bool wpa_auth_gtk_rekey_in_process(struct wpa_authenticator *wpa_auth)
1402{
1403 struct wpa_group *group;
1404
1405 for (group = wpa_auth->group; group; group = group->next) {
1406 if (group->GKeyDoneStations)
1407 return true;
1408 }
1409 return false;
1410}
1411
1412
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001413enum eapol_key_msg { PAIRWISE_2, PAIRWISE_4, GROUP_2, REQUEST };
1414
1415static bool wpa_auth_valid_key_desc_ver(struct wpa_authenticator *wpa_auth,
1416 struct wpa_state_machine *sm, u16 ver)
1417{
1418 if (ver > WPA_KEY_INFO_TYPE_AES_128_CMAC) {
1419 wpa_printf(MSG_INFO, "RSN: " MACSTR
1420 " used undefined Key Descriptor Version %d",
1421 MAC2STR(wpa_auth_get_spa(sm)), ver);
1422 return false;
1423 }
1424
1425 if (!wpa_use_akm_defined(sm->wpa_key_mgmt) &&
1426 wpa_use_cmac(sm->wpa_key_mgmt) &&
1427 ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) {
1428 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
1429 LOGGER_WARNING,
1430 "advertised support for AES-128-CMAC, but did not use it");
1431 return false;
1432 }
1433
1434 if (sm->pairwise != WPA_CIPHER_TKIP &&
1435 !wpa_use_akm_defined(sm->wpa_key_mgmt) &&
1436 !wpa_use_cmac(sm->wpa_key_mgmt) &&
1437 ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
1438 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
1439 LOGGER_WARNING,
1440 "did not use HMAC-SHA1-AES with CCMP/GCMP");
1441 return false;
1442 }
1443
1444 if (wpa_use_akm_defined(sm->wpa_key_mgmt) &&
1445 ver != WPA_KEY_INFO_TYPE_AKM_DEFINED) {
1446 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
1447 LOGGER_WARNING,
1448 "did not use EAPOL-Key descriptor version 0 as required for AKM-defined cases");
1449 return false;
1450 }
1451
1452 return true;
1453}
1454
1455
1456static bool wpa_auth_valid_request_counter(struct wpa_authenticator *wpa_auth,
1457 struct wpa_state_machine *sm,
1458 const u8 *replay_counter)
1459{
1460
1461 if (sm->req_replay_counter_used &&
1462 os_memcmp(replay_counter, sm->req_replay_counter,
1463 WPA_REPLAY_COUNTER_LEN) <= 0) {
1464 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
1465 LOGGER_WARNING,
1466 "received EAPOL-Key request with replayed counter");
1467 return false;
1468 }
1469
1470 return true;
1471}
1472
1473
1474static bool wpa_auth_valid_counter(struct wpa_authenticator *wpa_auth,
1475 struct wpa_state_machine *sm,
1476 const struct wpa_eapol_key *key,
1477 enum eapol_key_msg msg,
1478 const char *msgtxt)
1479{
1480 int i;
1481
1482 if (msg == REQUEST)
1483 return wpa_auth_valid_request_counter(wpa_auth, sm,
1484 key->replay_counter);
1485
1486 if (wpa_replay_counter_valid(sm->key_replay, key->replay_counter))
1487 return true;
1488
1489 if (msg == PAIRWISE_2 &&
1490 wpa_replay_counter_valid(sm->prev_key_replay,
1491 key->replay_counter) &&
1492 sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING &&
1493 os_memcmp(sm->SNonce, key->key_nonce, WPA_NONCE_LEN) != 0) {
1494 /*
1495 * Some supplicant implementations (e.g., Windows XP
1496 * WZC) update SNonce for each EAPOL-Key 2/4. This
1497 * breaks the workaround on accepting any of the
1498 * pending requests, so allow the SNonce to be updated
1499 * even if we have already sent out EAPOL-Key 3/4.
1500 */
1501 wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
1502 LOGGER_DEBUG,
1503 "Process SNonce update from STA based on retransmitted EAPOL-Key 1/4");
1504 sm->update_snonce = 1;
1505 os_memcpy(sm->alt_SNonce, sm->SNonce, WPA_NONCE_LEN);
1506 sm->alt_snonce_valid = true;
1507 os_memcpy(sm->alt_replay_counter,
1508 sm->key_replay[0].counter,
1509 WPA_REPLAY_COUNTER_LEN);
1510 return true;
1511 }
1512
1513 if (msg == PAIRWISE_4 && sm->alt_snonce_valid &&
1514 sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING &&
1515 os_memcmp(key->replay_counter, sm->alt_replay_counter,
1516 WPA_REPLAY_COUNTER_LEN) == 0) {
1517 /*
1518 * Supplicant may still be using the old SNonce since
1519 * there was two EAPOL-Key 2/4 messages and they had
1520 * different SNonce values.
1521 */
1522 wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
1523 LOGGER_DEBUG,
1524 "Try to process received EAPOL-Key 4/4 based on old Replay Counter and SNonce from an earlier EAPOL-Key 1/4");
1525 return true;
1526 }
1527
1528 if (msg == PAIRWISE_2 &&
1529 wpa_replay_counter_valid(sm->prev_key_replay,
1530 key->replay_counter) &&
1531 sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING) {
1532 wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
1533 LOGGER_DEBUG,
1534 "ignore retransmitted EAPOL-Key %s - SNonce did not change",
1535 msgtxt);
1536 } else {
1537 wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
1538 LOGGER_DEBUG,
1539 "received EAPOL-Key %s with unexpected replay counter",
1540 msgtxt);
1541 }
1542 for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) {
1543 if (!sm->key_replay[i].valid)
1544 break;
1545 wpa_hexdump(MSG_DEBUG, "pending replay counter",
1546 sm->key_replay[i].counter,
1547 WPA_REPLAY_COUNTER_LEN);
1548 }
1549 wpa_hexdump(MSG_DEBUG, "received replay counter",
1550 key->replay_counter, WPA_REPLAY_COUNTER_LEN);
1551 return false;
1552}
1553
1554
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001555void wpa_receive(struct wpa_authenticator *wpa_auth,
1556 struct wpa_state_machine *sm,
1557 u8 *data, size_t data_len)
1558{
1559 struct ieee802_1x_hdr *hdr;
1560 struct wpa_eapol_key *key;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001561 u16 key_info, ver, key_data_length;
1562 enum eapol_key_msg msg;
1563 const char *msgtxt;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001564 const u8 *key_data;
1565 size_t keyhdrlen, mic_len;
1566 u8 *mic;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001567 u8 *key_data_buf = NULL;
1568 size_t key_data_buf_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001569
Hai Shalomfdcde762020-04-02 11:19:20 -07001570 if (!wpa_auth || !wpa_auth->conf.wpa || !sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001571 return;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001572
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001573 wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL data", data, data_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001574
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001575 mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001576 keyhdrlen = sizeof(*key) + mic_len + 2;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001577
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001578 if (data_len < sizeof(*hdr) + keyhdrlen) {
1579 wpa_printf(MSG_DEBUG, "WPA: Ignore too short EAPOL-Key frame");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001580 return;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001581 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001582
1583 hdr = (struct ieee802_1x_hdr *) data;
1584 key = (struct wpa_eapol_key *) (hdr + 1);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001585 mic = (u8 *) (key + 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001586 key_info = WPA_GET_BE16(key->key_info);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001587 key_data = mic + mic_len + 2;
1588 key_data_length = WPA_GET_BE16(mic + mic_len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001589 wpa_printf(MSG_DEBUG, "WPA: Received EAPOL-Key from " MACSTR
Hai Shalomfdcde762020-04-02 11:19:20 -07001590 " key_info=0x%x type=%u mic_len=%zu key_data_length=%u",
Sunil Raviaf8751c2023-03-29 11:35:17 -07001591 MAC2STR(wpa_auth_get_spa(sm)), key_info, key->type,
Hai Shalomfdcde762020-04-02 11:19:20 -07001592 mic_len, key_data_length);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001593 wpa_hexdump(MSG_MSGDUMP,
1594 "WPA: EAPOL-Key header (ending before Key MIC)",
1595 key, sizeof(*key));
1596 wpa_hexdump(MSG_MSGDUMP, "WPA: EAPOL-Key Key MIC",
1597 mic, mic_len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001598 if (key_data_length > data_len - sizeof(*hdr) - keyhdrlen) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001599 wpa_printf(MSG_INFO,
1600 "WPA: Invalid EAPOL-Key frame - key_data overflow (%d > %zu)",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001601 key_data_length,
Hai Shalomfdcde762020-04-02 11:19:20 -07001602 data_len - sizeof(*hdr) - keyhdrlen);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001603 return;
1604 }
1605
1606 if (sm->wpa == WPA_VERSION_WPA2) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001607 if (key->type == EAPOL_KEY_TYPE_WPA) {
1608 /*
1609 * Some deployed station implementations seem to send
1610 * msg 4/4 with incorrect type value in WPA2 mode.
1611 */
Hai Shalomfdcde762020-04-02 11:19:20 -07001612 wpa_printf(MSG_DEBUG,
1613 "Workaround: Allow EAPOL-Key with unexpected WPA type in RSN mode");
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001614 } else if (key->type != EAPOL_KEY_TYPE_RSN) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001615 wpa_printf(MSG_DEBUG,
1616 "Ignore EAPOL-Key with unexpected type %d in RSN mode",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001617 key->type);
1618 return;
1619 }
1620 } else {
1621 if (key->type != EAPOL_KEY_TYPE_WPA) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001622 wpa_printf(MSG_DEBUG,
1623 "Ignore EAPOL-Key with unexpected type %d in WPA mode",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001624 key->type);
1625 return;
1626 }
1627 }
1628
1629 wpa_hexdump(MSG_DEBUG, "WPA: Received Key Nonce", key->key_nonce,
1630 WPA_NONCE_LEN);
1631 wpa_hexdump(MSG_DEBUG, "WPA: Received Replay Counter",
1632 key->replay_counter, WPA_REPLAY_COUNTER_LEN);
1633
1634 /* FIX: verify that the EAPOL-Key frame was encrypted if pairwise keys
1635 * are set */
1636
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001637 if (key_info & WPA_KEY_INFO_SMK_MESSAGE) {
1638 wpa_printf(MSG_DEBUG, "WPA: Ignore SMK message");
1639 return;
1640 }
1641
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001642 ver = key_info & WPA_KEY_INFO_TYPE_MASK;
1643 if (!wpa_auth_valid_key_desc_ver(wpa_auth, sm, ver))
1644 goto out;
1645 if (mic_len > 0 && (key_info & WPA_KEY_INFO_ENCR_KEY_DATA) &&
1646 sm->PTK_valid &&
1647 (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
1648 ver == WPA_KEY_INFO_TYPE_AES_128_CMAC ||
1649 wpa_use_aes_key_wrap(sm->wpa_key_mgmt)) &&
1650 key_data_length >= 8 && key_data_length % 8 == 0) {
1651 key_data_length -= 8; /* AES-WRAP adds 8 bytes */
1652 key_data_buf = os_malloc(key_data_length);
1653 if (!key_data_buf)
1654 goto out;
1655 key_data_buf_len = key_data_length;
1656 if (aes_unwrap(sm->PTK.kek, sm->PTK.kek_len,
1657 key_data_length / 8, key_data, key_data_buf)) {
1658 wpa_printf(MSG_INFO,
1659 "RSN: AES unwrap failed - could not decrypt EAPOL-Key key data");
1660 goto out;
1661 }
1662 key_data = key_data_buf;
1663 wpa_hexdump_key(MSG_DEBUG, "RSN: Decrypted EAPOL-Key Key Data",
1664 key_data, key_data_length);
1665 }
1666
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001667 if (key_info & WPA_KEY_INFO_REQUEST) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001668 msg = REQUEST;
1669 msgtxt = "Request";
1670 } else if (!(key_info & WPA_KEY_INFO_KEY_TYPE)) {
1671 msg = GROUP_2;
1672 msgtxt = "2/2 Group";
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001673 } else if (key_data_length == 0 ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001674 (sm->wpa == WPA_VERSION_WPA2 &&
1675 (!(key_info & WPA_KEY_INFO_ENCR_KEY_DATA) ||
1676 key_data_buf) &&
1677 (key_info & WPA_KEY_INFO_SECURE) &&
1678 !get_ie(key_data, key_data_length, WLAN_EID_RSN)) ||
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001679 (mic_len == 0 && (key_info & WPA_KEY_INFO_ENCR_KEY_DATA) &&
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001680 key_data_length == AES_BLOCK_SIZE)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001681 msg = PAIRWISE_4;
1682 msgtxt = "4/4 Pairwise";
1683 } else {
1684 msg = PAIRWISE_2;
1685 msgtxt = "2/4 Pairwise";
1686 }
1687
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001688 if (!wpa_auth_valid_counter(wpa_auth, sm, key, msg, msgtxt))
1689 goto out;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001690
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001691#ifdef CONFIG_FILS
1692 if (sm->wpa == WPA_VERSION_WPA2 && mic_len == 0 &&
1693 !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07001694 wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001695 "WPA: Encr Key Data bit not set even though AEAD cipher is supposed to be used - drop frame");
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001696 goto out;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001697 }
1698#endif /* CONFIG_FILS */
1699
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001700 switch (msg) {
1701 case PAIRWISE_2:
1702 if (sm->wpa_ptk_state != WPA_PTK_PTKSTART &&
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001703 sm->wpa_ptk_state != WPA_PTK_PTKCALCNEGOTIATING &&
1704 (!sm->update_snonce ||
1705 sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING)) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07001706 wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
1707 LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001708 "received EAPOL-Key msg 2/4 in invalid state (%d) - dropped",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001709 sm->wpa_ptk_state);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001710 goto out;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001711 }
1712 random_add_randomness(key->key_nonce, WPA_NONCE_LEN);
1713 if (sm->group->reject_4way_hs_for_entropy) {
1714 /*
1715 * The system did not have enough entropy to generate
1716 * strong random numbers. Reject the first 4-way
1717 * handshake(s) and collect some entropy based on the
1718 * information from it. Once enough entropy is
1719 * available, the next atempt will trigger GMK/Key
1720 * Counter update and the station will be allowed to
1721 * continue.
1722 */
Hai Shalomfdcde762020-04-02 11:19:20 -07001723 wpa_printf(MSG_DEBUG,
1724 "WPA: Reject 4-way handshake to collect more entropy for random number generation");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001725 random_mark_pool_ready();
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001726 wpa_sta_disconnect(wpa_auth, sm->addr,
1727 WLAN_REASON_PREV_AUTH_NOT_VALID);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001728 goto out;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001729 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001730 break;
1731 case PAIRWISE_4:
1732 if (sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING ||
1733 !sm->PTK_valid) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07001734 wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
1735 LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001736 "received EAPOL-Key msg 4/4 in invalid state (%d) - dropped",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001737 sm->wpa_ptk_state);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001738 goto out;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001739 }
1740 break;
1741 case GROUP_2:
1742 if (sm->wpa_ptk_group_state != WPA_PTK_GROUP_REKEYNEGOTIATING
1743 || !sm->PTK_valid) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07001744 wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
1745 LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001746 "received EAPOL-Key msg 2/2 in invalid state (%d) - dropped",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001747 sm->wpa_ptk_group_state);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001748 goto out;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001749 }
1750 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001751 case REQUEST:
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001752 if (sm->wpa_ptk_state == WPA_PTK_PTKSTART ||
1753 sm->wpa_ptk_state == WPA_PTK_PTKCALCNEGOTIATING ||
1754 sm->wpa_ptk_state == WPA_PTK_PTKCALCNEGOTIATING2 ||
1755 sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING) {
1756 wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
1757 LOGGER_INFO,
1758 "received EAPOL-Key Request in invalid state (%d) - dropped",
1759 sm->wpa_ptk_state);
1760 goto out;
1761 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001762 break;
1763 }
1764
Sunil Raviaf8751c2023-03-29 11:35:17 -07001765 wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001766 "received EAPOL-Key frame (%s)", msgtxt);
1767
1768 if (key_info & WPA_KEY_INFO_ACK) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07001769 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001770 "received invalid EAPOL-Key: Key Ack set");
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001771 goto out;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001772 }
1773
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001774 if (!wpa_key_mgmt_fils(sm->wpa_key_mgmt) &&
1775 !(key_info & WPA_KEY_INFO_MIC)) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07001776 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001777 "received invalid EAPOL-Key: Key MIC not set");
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001778 goto out;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001779 }
1780
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001781#ifdef CONFIG_FILS
1782 if (wpa_key_mgmt_fils(sm->wpa_key_mgmt) &&
1783 (key_info & WPA_KEY_INFO_MIC)) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07001784 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001785 "received invalid EAPOL-Key: Key MIC set");
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001786 goto out;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001787 }
1788#endif /* CONFIG_FILS */
1789
Hai Shalome21d4e82020-04-29 16:34:06 -07001790 sm->MICVerified = false;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001791 if (sm->PTK_valid && !sm->update_snonce) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001792 if (mic_len &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001793 wpa_verify_key_mic(sm->wpa_key_mgmt, sm->pmk_len, &sm->PTK,
1794 data, data_len) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001795 (msg != PAIRWISE_4 || !sm->alt_snonce_valid ||
1796 wpa_try_alt_snonce(sm, data, data_len))) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07001797 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
1798 LOGGER_INFO,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001799 "received EAPOL-Key with invalid MIC");
Hai Shalom74f70d42019-02-11 14:42:39 -08001800#ifdef TEST_FUZZ
1801 wpa_printf(MSG_INFO,
1802 "TEST: Ignore Key MIC failure for fuzz testing");
1803 goto continue_fuzz;
1804#endif /* TEST_FUZZ */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001805 goto out;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001806 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001807#ifdef CONFIG_FILS
1808 if (!mic_len &&
1809 wpa_aead_decrypt(sm, &sm->PTK, data, data_len,
1810 &key_data_length) < 0) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07001811 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
1812 LOGGER_INFO,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001813 "received EAPOL-Key with invalid MIC");
Hai Shalom74f70d42019-02-11 14:42:39 -08001814#ifdef TEST_FUZZ
1815 wpa_printf(MSG_INFO,
1816 "TEST: Ignore Key MIC failure for fuzz testing");
1817 goto continue_fuzz;
1818#endif /* TEST_FUZZ */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001819 goto out;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001820 }
1821#endif /* CONFIG_FILS */
Hai Shalom74f70d42019-02-11 14:42:39 -08001822#ifdef TEST_FUZZ
1823 continue_fuzz:
1824#endif /* TEST_FUZZ */
Hai Shalome21d4e82020-04-29 16:34:06 -07001825 sm->MICVerified = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001826 eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm);
1827 sm->pending_1_of_4_timeout = 0;
1828 }
1829
1830 if (key_info & WPA_KEY_INFO_REQUEST) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001831 if (!(key_info & WPA_KEY_INFO_SECURE)) {
1832 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
1833 LOGGER_INFO,
1834 "received EAPOL-Key request without Secure=1");
1835 goto out;
1836 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001837 if (sm->MICVerified) {
1838 sm->req_replay_counter_used = 1;
1839 os_memcpy(sm->req_replay_counter, key->replay_counter,
1840 WPA_REPLAY_COUNTER_LEN);
1841 } else {
Sunil Raviaf8751c2023-03-29 11:35:17 -07001842 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
1843 LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001844 "received EAPOL-Key request with invalid MIC");
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001845 goto out;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001846 }
1847
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001848 if (key_info & WPA_KEY_INFO_ERROR) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001849 if (wpa_receive_error_report(
1850 wpa_auth, sm,
1851 !(key_info & WPA_KEY_INFO_KEY_TYPE)) > 0)
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001852 goto out; /* STA entry was removed */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001853 } else if (key_info & WPA_KEY_INFO_KEY_TYPE) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07001854 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
1855 LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001856 "received EAPOL-Key Request for new 4-Way Handshake");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001857 wpa_request_new_ptk(sm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001858 } else {
Sunil Raviaf8751c2023-03-29 11:35:17 -07001859 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
1860 LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001861 "received EAPOL-Key Request for GTK rekeying");
Sunil Ravi7f769292024-07-23 22:21:32 +00001862
1863 eloop_cancel_timeout(wpa_rekey_gtk,
1864 wpa_get_primary_auth(wpa_auth),
1865 NULL);
Hai Shaloma20dcd72022-02-04 13:43:00 -08001866 if (wpa_auth_gtk_rekey_in_process(wpa_auth))
1867 wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG,
1868 "skip new GTK rekey - already in process");
1869 else
Sunil Ravi7f769292024-07-23 22:21:32 +00001870 wpa_rekey_gtk(wpa_get_primary_auth(wpa_auth),
1871 NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001872 }
1873 } else {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001874 /* Do not allow the same key replay counter to be reused. */
1875 wpa_replay_counter_mark_invalid(sm->key_replay,
1876 key->replay_counter);
1877
1878 if (msg == PAIRWISE_2) {
1879 /*
1880 * Maintain a copy of the pending EAPOL-Key frames in
1881 * case the EAPOL-Key frame was retransmitted. This is
1882 * needed to allow EAPOL-Key msg 2/4 reply to another
1883 * pending msg 1/4 to update the SNonce to work around
1884 * unexpected supplicant behavior.
1885 */
1886 os_memcpy(sm->prev_key_replay, sm->key_replay,
1887 sizeof(sm->key_replay));
1888 } else {
1889 os_memset(sm->prev_key_replay, 0,
1890 sizeof(sm->prev_key_replay));
1891 }
1892
1893 /*
1894 * Make sure old valid counters are not accepted anymore and
1895 * do not get copied again.
1896 */
1897 wpa_replay_counter_mark_invalid(sm->key_replay, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001898 }
1899
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001900 os_free(sm->last_rx_eapol_key);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001901 sm->last_rx_eapol_key = os_memdup(data, data_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07001902 if (!sm->last_rx_eapol_key)
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001903 goto out;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001904 sm->last_rx_eapol_key_len = data_len;
1905
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001906 sm->rx_eapol_key_secure = !!(key_info & WPA_KEY_INFO_SECURE);
Hai Shalome21d4e82020-04-29 16:34:06 -07001907 sm->EAPOLKeyReceived = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001908 sm->EAPOLKeyPairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE);
1909 sm->EAPOLKeyRequest = !!(key_info & WPA_KEY_INFO_REQUEST);
Sunil Ravic0f5d412024-09-11 22:12:49 +00001910 if (msg == PAIRWISE_2)
1911 os_memcpy(sm->SNonce, key->key_nonce, WPA_NONCE_LEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001912 wpa_sm_step(sm);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001913
1914out:
1915 bin_clear_free(key_data_buf, key_data_buf_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001916}
1917
1918
1919static int wpa_gmk_to_gtk(const u8 *gmk, const char *label, const u8 *addr,
1920 const u8 *gnonce, u8 *gtk, size_t gtk_len)
1921{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001922 u8 data[ETH_ALEN + WPA_NONCE_LEN + 8 + WPA_GTK_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001923 u8 *pos;
1924 int ret = 0;
1925
1926 /* GTK = PRF-X(GMK, "Group key expansion",
1927 * AA || GNonce || Time || random data)
1928 * The example described in the IEEE 802.11 standard uses only AA and
1929 * GNonce as inputs here. Add some more entropy since this derivation
1930 * is done only at the Authenticator and as such, does not need to be
1931 * exactly same.
1932 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001933 os_memset(data, 0, sizeof(data));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001934 os_memcpy(data, addr, ETH_ALEN);
1935 os_memcpy(data + ETH_ALEN, gnonce, WPA_NONCE_LEN);
1936 pos = data + ETH_ALEN + WPA_NONCE_LEN;
1937 wpa_get_ntp_timestamp(pos);
Hai Shalom74f70d42019-02-11 14:42:39 -08001938#ifdef TEST_FUZZ
1939 os_memset(pos, 0xef, 8);
1940#endif /* TEST_FUZZ */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001941 pos += 8;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001942 if (random_get_bytes(pos, gtk_len) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001943 ret = -1;
1944
Roshan Pius3a1667e2018-07-03 15:17:14 -07001945#ifdef CONFIG_SHA384
1946 if (sha384_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data),
1947 gtk, gtk_len) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001948 ret = -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001949#else /* CONFIG_SHA384 */
1950#ifdef CONFIG_SHA256
1951 if (sha256_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data),
1952 gtk, gtk_len) < 0)
1953 ret = -1;
1954#else /* CONFIG_SHA256 */
1955 if (sha1_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data),
1956 gtk, gtk_len) < 0)
1957 ret = -1;
1958#endif /* CONFIG_SHA256 */
1959#endif /* CONFIG_SHA384 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001960
Hai Shalom81f62d82019-07-22 12:10:00 -07001961 forced_memzero(data, sizeof(data));
1962
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001963 return ret;
1964}
1965
1966
1967static void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx)
1968{
1969 struct wpa_authenticator *wpa_auth = eloop_ctx;
1970 struct wpa_state_machine *sm = timeout_ctx;
1971
Sunil Ravia04bd252022-05-02 22:54:18 -07001972 if (sm->waiting_radius_psk) {
1973 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
1974 "Ignore EAPOL-Key timeout while waiting for RADIUS PSK");
1975 return;
1976 }
1977
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001978 sm->pending_1_of_4_timeout = 0;
Sunil Raviaf8751c2023-03-29 11:35:17 -07001979 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
1980 "EAPOL-Key timeout");
Hai Shalome21d4e82020-04-29 16:34:06 -07001981 sm->TimeoutEvt = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001982 wpa_sm_step(sm);
1983}
1984
1985
1986void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
1987 struct wpa_state_machine *sm, int key_info,
1988 const u8 *key_rsc, const u8 *nonce,
1989 const u8 *kde, size_t kde_len,
1990 int keyidx, int encr, int force_version)
1991{
Hai Shalomfdcde762020-04-02 11:19:20 -07001992 struct wpa_auth_config *conf = &wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001993 struct ieee802_1x_hdr *hdr;
1994 struct wpa_eapol_key *key;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001995 size_t len, mic_len, keyhdrlen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001996 int alg;
1997 int key_data_len, pad_len = 0;
1998 u8 *buf, *pos;
1999 int version, pairwise;
2000 int i;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002001 u8 *key_mic, *key_data;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002002
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002003 mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002004 keyhdrlen = sizeof(*key) + mic_len + 2;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002005
2006 len = sizeof(struct ieee802_1x_hdr) + keyhdrlen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002007
2008 if (force_version)
2009 version = force_version;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002010 else if (wpa_use_akm_defined(sm->wpa_key_mgmt))
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002011 version = WPA_KEY_INFO_TYPE_AKM_DEFINED;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002012 else if (wpa_use_cmac(sm->wpa_key_mgmt))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002013 version = WPA_KEY_INFO_TYPE_AES_128_CMAC;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002014 else if (sm->pairwise != WPA_CIPHER_TKIP)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002015 version = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;
2016 else
2017 version = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
2018
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002019 pairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002020
Hai Shalomfdcde762020-04-02 11:19:20 -07002021 wpa_printf(MSG_DEBUG,
2022 "WPA: Send EAPOL(version=%d secure=%d mic=%d ack=%d install=%d pairwise=%d kde_len=%zu keyidx=%d encr=%d)",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002023 version,
2024 (key_info & WPA_KEY_INFO_SECURE) ? 1 : 0,
2025 (key_info & WPA_KEY_INFO_MIC) ? 1 : 0,
2026 (key_info & WPA_KEY_INFO_ACK) ? 1 : 0,
2027 (key_info & WPA_KEY_INFO_INSTALL) ? 1 : 0,
Hai Shalomfdcde762020-04-02 11:19:20 -07002028 pairwise, kde_len, keyidx, encr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002029
2030 key_data_len = kde_len;
2031
2032 if ((version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
Roshan Pius3a1667e2018-07-03 15:17:14 -07002033 wpa_use_aes_key_wrap(sm->wpa_key_mgmt) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002034 version == WPA_KEY_INFO_TYPE_AES_128_CMAC) && encr) {
2035 pad_len = key_data_len % 8;
2036 if (pad_len)
2037 pad_len = 8 - pad_len;
2038 key_data_len += pad_len + 8;
2039 }
2040
2041 len += key_data_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002042 if (!mic_len && encr)
2043 len += AES_BLOCK_SIZE;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002044
2045 hdr = os_zalloc(len);
Hai Shalomfdcde762020-04-02 11:19:20 -07002046 if (!hdr)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002047 return;
Hai Shalomfdcde762020-04-02 11:19:20 -07002048 hdr->version = conf->eapol_version;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002049 hdr->type = IEEE802_1X_TYPE_EAPOL_KEY;
2050 hdr->length = host_to_be16(len - sizeof(*hdr));
2051 key = (struct wpa_eapol_key *) (hdr + 1);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002052 key_mic = (u8 *) (key + 1);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002053 key_data = ((u8 *) (hdr + 1)) + keyhdrlen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002054
2055 key->type = sm->wpa == WPA_VERSION_WPA2 ?
2056 EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
2057 key_info |= version;
2058 if (encr && sm->wpa == WPA_VERSION_WPA2)
2059 key_info |= WPA_KEY_INFO_ENCR_KEY_DATA;
2060 if (sm->wpa != WPA_VERSION_WPA2)
2061 key_info |= keyidx << WPA_KEY_INFO_KEY_INDEX_SHIFT;
2062 WPA_PUT_BE16(key->key_info, key_info);
2063
Hai Shalomfdcde762020-04-02 11:19:20 -07002064 alg = pairwise ? sm->pairwise : conf->wpa_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002065 if (sm->wpa == WPA_VERSION_WPA2 && !pairwise)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002066 WPA_PUT_BE16(key->key_length, 0);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002067 else
2068 WPA_PUT_BE16(key->key_length, wpa_cipher_key_len(alg));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002069
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002070 for (i = RSNA_MAX_EAPOL_RETRIES - 1; i > 0; i--) {
2071 sm->key_replay[i].valid = sm->key_replay[i - 1].valid;
2072 os_memcpy(sm->key_replay[i].counter,
2073 sm->key_replay[i - 1].counter,
2074 WPA_REPLAY_COUNTER_LEN);
2075 }
2076 inc_byte_array(sm->key_replay[0].counter, WPA_REPLAY_COUNTER_LEN);
2077 os_memcpy(key->replay_counter, sm->key_replay[0].counter,
2078 WPA_REPLAY_COUNTER_LEN);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002079 wpa_hexdump(MSG_DEBUG, "WPA: Replay Counter",
2080 key->replay_counter, WPA_REPLAY_COUNTER_LEN);
Hai Shalome21d4e82020-04-29 16:34:06 -07002081 sm->key_replay[0].valid = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002082
2083 if (nonce)
2084 os_memcpy(key->key_nonce, nonce, WPA_NONCE_LEN);
2085
2086 if (key_rsc)
2087 os_memcpy(key->key_rsc, key_rsc, WPA_KEY_RSC_LEN);
2088
Sunil Ravic0f5d412024-09-11 22:12:49 +00002089#ifdef CONFIG_TESTING_OPTIONS
2090 if (conf->eapol_key_reserved_random)
2091 random_get_bytes(key->key_id, sizeof(key->key_id));
2092#endif /* CONFIG_TESTING_OPTIONS */
2093
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002094 if (kde && !encr) {
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002095 os_memcpy(key_data, kde, kde_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002096 WPA_PUT_BE16(key_mic + mic_len, kde_len);
2097#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07002098 } else if (!mic_len && kde) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002099 const u8 *aad[1];
2100 size_t aad_len[1];
2101
2102 WPA_PUT_BE16(key_mic, AES_BLOCK_SIZE + kde_len);
2103 wpa_hexdump_key(MSG_DEBUG, "Plaintext EAPOL-Key Key Data",
2104 kde, kde_len);
2105
2106 wpa_hexdump_key(MSG_DEBUG, "WPA: KEK",
2107 sm->PTK.kek, sm->PTK.kek_len);
2108 /* AES-SIV AAD from EAPOL protocol version field (inclusive) to
2109 * to Key Data (exclusive). */
2110 aad[0] = (u8 *) hdr;
2111 aad_len[0] = key_mic + 2 - (u8 *) hdr;
2112 if (aes_siv_encrypt(sm->PTK.kek, sm->PTK.kek_len, kde, kde_len,
2113 1, aad, aad_len, key_mic + 2) < 0) {
2114 wpa_printf(MSG_DEBUG, "WPA: AES-SIV encryption failed");
2115 return;
2116 }
2117
2118 wpa_hexdump(MSG_DEBUG, "WPA: Encrypted Key Data from SIV",
2119 key_mic + 2, AES_BLOCK_SIZE + kde_len);
2120#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002121 } else if (encr && kde) {
2122 buf = os_zalloc(key_data_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07002123 if (!buf) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002124 os_free(hdr);
2125 return;
2126 }
2127 pos = buf;
2128 os_memcpy(pos, kde, kde_len);
2129 pos += kde_len;
2130
2131 if (pad_len)
2132 *pos++ = 0xdd;
2133
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002134 wpa_hexdump_key(MSG_DEBUG,
2135 "Plaintext EAPOL-Key Key Data (+ padding)",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002136 buf, key_data_len);
2137 if (version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
Roshan Pius3a1667e2018-07-03 15:17:14 -07002138 wpa_use_aes_key_wrap(sm->wpa_key_mgmt) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002139 version == WPA_KEY_INFO_TYPE_AES_128_CMAC) {
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002140 wpa_hexdump_key(MSG_DEBUG, "RSN: AES-WRAP using KEK",
2141 sm->PTK.kek, sm->PTK.kek_len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002142 if (aes_wrap(sm->PTK.kek, sm->PTK.kek_len,
2143 (key_data_len - 8) / 8, buf, key_data)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002144 os_free(hdr);
Sunil Ravia04bd252022-05-02 22:54:18 -07002145 bin_clear_free(buf, key_data_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002146 return;
2147 }
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002148 wpa_hexdump(MSG_DEBUG,
2149 "RSN: Encrypted Key Data from AES-WRAP",
2150 key_data, key_data_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002151 WPA_PUT_BE16(key_mic + mic_len, key_data_len);
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002152#if !defined(CONFIG_NO_RC4) && !defined(CONFIG_FIPS)
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002153 } else if (sm->PTK.kek_len == 16) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002154 u8 ek[32];
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002155
2156 wpa_printf(MSG_DEBUG,
2157 "WPA: Encrypt Key Data using RC4");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002158 os_memcpy(key->key_iv,
2159 sm->group->Counter + WPA_NONCE_LEN - 16, 16);
2160 inc_byte_array(sm->group->Counter, WPA_NONCE_LEN);
2161 os_memcpy(ek, key->key_iv, 16);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002162 os_memcpy(ek + 16, sm->PTK.kek, sm->PTK.kek_len);
2163 os_memcpy(key_data, buf, key_data_len);
2164 rc4_skip(ek, 32, 256, key_data, key_data_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002165 WPA_PUT_BE16(key_mic + mic_len, key_data_len);
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002166#endif /* !(CONFIG_NO_RC4 || CONFIG_FIPS) */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002167 } else {
2168 os_free(hdr);
Sunil Ravia04bd252022-05-02 22:54:18 -07002169 bin_clear_free(buf, key_data_len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002170 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002171 }
Sunil Ravia04bd252022-05-02 22:54:18 -07002172 bin_clear_free(buf, key_data_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002173 }
2174
2175 if (key_info & WPA_KEY_INFO_MIC) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002176 if (!sm->PTK_valid || !mic_len) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07002177 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
2178 LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07002179 "PTK not valid when sending EAPOL-Key frame");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002180 os_free(hdr);
2181 return;
2182 }
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002183
Roshan Pius3a1667e2018-07-03 15:17:14 -07002184 if (wpa_eapol_key_mic(sm->PTK.kck, sm->PTK.kck_len,
2185 sm->wpa_key_mgmt, version,
2186 (u8 *) hdr, len, key_mic) < 0) {
2187 os_free(hdr);
2188 return;
2189 }
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002190#ifdef CONFIG_TESTING_OPTIONS
2191 if (!pairwise &&
Hai Shalomfdcde762020-04-02 11:19:20 -07002192 conf->corrupt_gtk_rekey_mic_probability > 0.0 &&
2193 drand48() < conf->corrupt_gtk_rekey_mic_probability) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07002194 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
2195 LOGGER_INFO,
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002196 "Corrupting group EAPOL-Key Key MIC");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002197 key_mic[0]++;
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002198 }
2199#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002200 }
2201
Hai Shalomfdcde762020-04-02 11:19:20 -07002202 wpa_auth_set_eapol(wpa_auth, sm->addr, WPA_EAPOL_inc_EapolFramesTx, 1);
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002203 wpa_hexdump(MSG_DEBUG, "Send EAPOL-Key msg", hdr, len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002204 wpa_auth_send_eapol(wpa_auth, sm->addr, (u8 *) hdr, len,
Kai Shie75b0652020-11-24 20:31:29 -08002205 sm->pairwise_set);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002206 os_free(hdr);
2207}
2208
2209
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002210static int wpa_auth_get_sta_count(struct wpa_authenticator *wpa_auth)
2211{
2212 if (!wpa_auth->cb->get_sta_count)
2213 return -1;
2214
2215 return wpa_auth->cb->get_sta_count(wpa_auth->cb_ctx);
2216}
2217
2218
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002219static void wpa_send_eapol(struct wpa_authenticator *wpa_auth,
2220 struct wpa_state_machine *sm, int key_info,
2221 const u8 *key_rsc, const u8 *nonce,
2222 const u8 *kde, size_t kde_len,
2223 int keyidx, int encr)
2224{
2225 int timeout_ms;
2226 int pairwise = key_info & WPA_KEY_INFO_KEY_TYPE;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002227 u32 ctr;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002228
Hai Shalomfdcde762020-04-02 11:19:20 -07002229 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002230 return;
2231
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002232 ctr = pairwise ? sm->TimeoutCtr : sm->GTimeoutCtr;
2233
2234#ifdef CONFIG_TESTING_OPTIONS
2235 /* When delay_eapol_tx is true, delay the EAPOL-Key transmission by
2236 * sending it only on the last attempt after all timeouts for the prior
2237 * skipped attemps. */
2238 if (wpa_auth->conf.delay_eapol_tx &&
2239 ctr != wpa_auth->conf.wpa_pairwise_update_count) {
2240 wpa_msg(sm->wpa_auth->conf.msg_ctx, MSG_INFO,
2241 "DELAY-EAPOL-TX-%d", ctr);
2242 goto skip_tx;
2243 }
2244#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002245 __wpa_send_eapol(wpa_auth, sm, key_info, key_rsc, nonce, kde, kde_len,
2246 keyidx, encr, 0);
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002247#ifdef CONFIG_TESTING_OPTIONS
2248skip_tx:
2249#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002250
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002251 if (ctr == 1 && wpa_auth->conf.tx_status) {
2252 if (pairwise)
2253 timeout_ms = eapol_key_timeout_first;
2254 else if (wpa_auth_get_sta_count(wpa_auth) > 100)
2255 timeout_ms = eapol_key_timeout_first_group * 2;
2256 else
2257 timeout_ms = eapol_key_timeout_first_group;
2258 } else {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002259 timeout_ms = eapol_key_timeout_subseq;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002260 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002261 if (wpa_auth->conf.wpa_disable_eapol_key_retries &&
2262 (!pairwise || (key_info & WPA_KEY_INFO_MIC)))
2263 timeout_ms = eapol_key_timeout_no_retrans;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002264 if (pairwise && ctr == 1 && !(key_info & WPA_KEY_INFO_MIC))
2265 sm->pending_1_of_4_timeout = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08002266#ifdef TEST_FUZZ
2267 timeout_ms = 1;
2268#endif /* TEST_FUZZ */
Kai Shie75b0652020-11-24 20:31:29 -08002269#ifdef CONFIG_TESTING_OPTIONS
2270 if(wpa_auth->conf.enable_eapol_large_timeout) {
2271 timeout_ms = 50 * 1000;
2272 }
2273#endif
Hai Shalomfdcde762020-04-02 11:19:20 -07002274 wpa_printf(MSG_DEBUG,
2275 "WPA: Use EAPOL-Key timeout of %u ms (retry counter %u)",
2276 timeout_ms, ctr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002277 eloop_register_timeout(timeout_ms / 1000, (timeout_ms % 1000) * 1000,
2278 wpa_send_eapol_timeout, wpa_auth, sm);
2279}
2280
2281
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002282static int wpa_verify_key_mic(int akmp, size_t pmk_len, struct wpa_ptk *PTK,
2283 u8 *data, size_t data_len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002284{
2285 struct ieee802_1x_hdr *hdr;
2286 struct wpa_eapol_key *key;
2287 u16 key_info;
2288 int ret = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002289 u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN], *mic_pos;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002290 size_t mic_len = wpa_mic_len(akmp, pmk_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002291
2292 if (data_len < sizeof(*hdr) + sizeof(*key))
2293 return -1;
2294
2295 hdr = (struct ieee802_1x_hdr *) data;
2296 key = (struct wpa_eapol_key *) (hdr + 1);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002297 mic_pos = (u8 *) (key + 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002298 key_info = WPA_GET_BE16(key->key_info);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002299 os_memcpy(mic, mic_pos, mic_len);
2300 os_memset(mic_pos, 0, mic_len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002301 if (wpa_eapol_key_mic(PTK->kck, PTK->kck_len, akmp,
2302 key_info & WPA_KEY_INFO_TYPE_MASK,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002303 data, data_len, mic_pos) ||
2304 os_memcmp_const(mic, mic_pos, mic_len) != 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002305 ret = -1;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002306 os_memcpy(mic_pos, mic, mic_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002307 return ret;
2308}
2309
2310
2311void wpa_remove_ptk(struct wpa_state_machine *sm)
2312{
Hai Shalome21d4e82020-04-29 16:34:06 -07002313 sm->PTK_valid = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002314 os_memset(&sm->PTK, 0, sizeof(sm->PTK));
Hai Shalom60840252021-02-19 19:02:11 -08002315
2316 wpa_auth_remove_ptksa(sm->wpa_auth, sm->addr, sm->pairwise);
2317
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002318 if (wpa_auth_set_key(sm->wpa_auth, 0, WPA_ALG_NONE, sm->addr, 0, NULL,
Hai Shalomfdcde762020-04-02 11:19:20 -07002319 0, KEY_FLAG_PAIRWISE))
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002320 wpa_printf(MSG_DEBUG,
2321 "RSN: PTK removal from the driver failed");
Hai Shalomfdcde762020-04-02 11:19:20 -07002322 if (sm->use_ext_key_id &&
2323 wpa_auth_set_key(sm->wpa_auth, 0, WPA_ALG_NONE, sm->addr, 1, NULL,
2324 0, KEY_FLAG_PAIRWISE))
2325 wpa_printf(MSG_DEBUG,
2326 "RSN: PTK Key ID 1 removal from the driver failed");
Hai Shalome21d4e82020-04-29 16:34:06 -07002327 sm->pairwise_set = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002328 eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm);
2329}
2330
2331
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002332int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002333{
2334 int remove_ptk = 1;
2335
Hai Shalomfdcde762020-04-02 11:19:20 -07002336 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002337 return -1;
2338
Sunil Raviaf8751c2023-03-29 11:35:17 -07002339 wpa_auth_vlogger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002340 "event %d notification", event);
2341
2342 switch (event) {
2343 case WPA_AUTH:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002344#ifdef CONFIG_MESH
2345 /* PTKs are derived through AMPE */
2346 if (wpa_auth_start_ampe(sm->wpa_auth, sm->addr)) {
2347 /* not mesh */
2348 break;
2349 }
2350 return 0;
2351#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002352 case WPA_ASSOC:
2353 break;
2354 case WPA_DEAUTH:
2355 case WPA_DISASSOC:
Hai Shalome21d4e82020-04-29 16:34:06 -07002356 sm->DeauthenticationRequest = true;
Hai Shalom1dc4d202019-04-29 16:22:27 -07002357 os_memset(sm->PMK, 0, sizeof(sm->PMK));
2358 sm->pmk_len = 0;
Sunil Ravia04bd252022-05-02 22:54:18 -07002359#ifdef CONFIG_IEEE80211R_AP
Hai Shalom1dc4d202019-04-29 16:22:27 -07002360 os_memset(sm->xxkey, 0, sizeof(sm->xxkey));
2361 sm->xxkey_len = 0;
Hai Shalom81f62d82019-07-22 12:10:00 -07002362 os_memset(sm->pmk_r1, 0, sizeof(sm->pmk_r1));
2363 sm->pmk_r1_len = 0;
Hai Shalom1dc4d202019-04-29 16:22:27 -07002364#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002365 break;
2366 case WPA_REAUTH:
2367 case WPA_REAUTH_EAPOL:
2368 if (!sm->started) {
2369 /*
2370 * When using WPS, we may end up here if the STA
2371 * manages to re-associate without the previous STA
2372 * entry getting removed. Consequently, we need to make
2373 * sure that the WPA state machines gets initialized
2374 * properly at this point.
2375 */
Hai Shalomfdcde762020-04-02 11:19:20 -07002376 wpa_printf(MSG_DEBUG,
2377 "WPA state machine had not been started - initialize now");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002378 sm->started = 1;
Hai Shalome21d4e82020-04-29 16:34:06 -07002379 sm->Init = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002380 if (wpa_sm_step(sm) == 1)
2381 return 1; /* should not really happen */
Hai Shalome21d4e82020-04-29 16:34:06 -07002382 sm->Init = false;
Sunil Ravi79e6c4f2025-01-04 00:47:06 +00002383
2384 if (wpa_auth_4way_handshake_offload(sm->wpa_auth))
2385 wpa_printf(MSG_DEBUG,
2386 "Skip EAPOL for 4-way handshake offload case");
2387 else
2388 sm->AuthenticationRequest = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002389 break;
2390 }
Hai Shalomfdcde762020-04-02 11:19:20 -07002391
Sunil Ravia04bd252022-05-02 22:54:18 -07002392 if (sm->ptkstart_without_success > 3) {
2393 wpa_printf(MSG_INFO,
2394 "WPA: Multiple EAP reauth attempts without 4-way handshake completion, disconnect "
2395 MACSTR, MAC2STR(sm->addr));
2396 sm->Disconnect = true;
2397 break;
2398 }
2399
Hai Shalomfdcde762020-04-02 11:19:20 -07002400 if (!sm->use_ext_key_id &&
2401 sm->wpa_auth->conf.wpa_deny_ptk0_rekey) {
2402 wpa_printf(MSG_INFO,
2403 "WPA: PTK0 rekey not allowed, disconnect "
Sunil Raviaf8751c2023-03-29 11:35:17 -07002404 MACSTR, MAC2STR(wpa_auth_get_spa(sm)));
Hai Shalome21d4e82020-04-29 16:34:06 -07002405 sm->Disconnect = true;
Hai Shalomfdcde762020-04-02 11:19:20 -07002406 /* Try to encourage the STA to reconnect */
2407 sm->disconnect_reason =
2408 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA;
2409 break;
2410 }
2411
2412 if (sm->use_ext_key_id)
2413 sm->keyidx_active ^= 1; /* flip Key ID */
2414
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002415 if (sm->GUpdateStationKeys) {
2416 /*
2417 * Reauthentication cancels the pending group key
2418 * update for this STA.
2419 */
Sunil Ravi7f769292024-07-23 22:21:32 +00002420 wpa_gkeydone_sta(sm);
Hai Shalome21d4e82020-04-29 16:34:06 -07002421 sm->PtkGroupInit = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002422 }
Hai Shalome21d4e82020-04-29 16:34:06 -07002423 sm->ReAuthenticationRequest = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002424 break;
2425 case WPA_ASSOC_FT:
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002426#ifdef CONFIG_IEEE80211R_AP
Hai Shalomfdcde762020-04-02 11:19:20 -07002427 wpa_printf(MSG_DEBUG,
2428 "FT: Retry PTK configuration after association");
Hai Shalomb755a2a2020-04-23 21:49:02 -07002429 wpa_ft_install_ptk(sm, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002430
2431 /* Using FT protocol, not WPA auth state machine */
2432 sm->ft_completed = 1;
Hai Shalom81f62d82019-07-22 12:10:00 -07002433 wpa_auth_set_ptk_rekey_timer(sm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002434 return 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002435#else /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002436 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002437#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002438 case WPA_ASSOC_FILS:
2439#ifdef CONFIG_FILS
2440 wpa_printf(MSG_DEBUG,
2441 "FILS: TK configuration after association");
2442 fils_set_tk(sm);
2443 sm->fils_completed = 1;
2444 return 0;
2445#else /* CONFIG_FILS */
2446 break;
2447#endif /* CONFIG_FILS */
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02002448 case WPA_DRV_STA_REMOVED:
Hai Shalome21d4e82020-04-29 16:34:06 -07002449 sm->tk_already_set = false;
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02002450 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002451 }
2452
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002453#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002454 sm->ft_completed = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002455#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002456
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002457 if (sm->mgmt_frame_prot && event == WPA_AUTH)
2458 remove_ptk = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002459#ifdef CONFIG_FILS
2460 if (wpa_key_mgmt_fils(sm->wpa_key_mgmt) &&
2461 (event == WPA_AUTH || event == WPA_ASSOC))
2462 remove_ptk = 0;
2463#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002464
2465 if (remove_ptk) {
Hai Shalome21d4e82020-04-29 16:34:06 -07002466 sm->PTK_valid = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002467 os_memset(&sm->PTK, 0, sizeof(sm->PTK));
2468
2469 if (event != WPA_REAUTH_EAPOL)
2470 wpa_remove_ptk(sm);
2471 }
2472
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002473 if (sm->in_step_loop) {
2474 /*
2475 * wpa_sm_step() is already running - avoid recursive call to
2476 * it by making the existing loop process the new update.
2477 */
Hai Shalome21d4e82020-04-29 16:34:06 -07002478 sm->changed = true;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002479 return 0;
2480 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002481 return wpa_sm_step(sm);
2482}
2483
2484
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002485SM_STATE(WPA_PTK, INITIALIZE)
2486{
2487 SM_ENTRY_MA(WPA_PTK, INITIALIZE, wpa_ptk);
2488 if (sm->Init) {
2489 /* Init flag is not cleared here, so avoid busy
2490 * loop by claiming nothing changed. */
Hai Shalome21d4e82020-04-29 16:34:06 -07002491 sm->changed = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002492 }
2493
2494 sm->keycount = 0;
2495 if (sm->GUpdateStationKeys)
Sunil Ravi7f769292024-07-23 22:21:32 +00002496 wpa_gkeydone_sta(sm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002497 if (sm->wpa == WPA_VERSION_WPA)
Hai Shalome21d4e82020-04-29 16:34:06 -07002498 sm->PInitAKeys = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002499 if (1 /* Unicast cipher supported AND (ESS OR ((IBSS or WDS) and
2500 * Local AA > Remote AA)) */) {
Hai Shalome21d4e82020-04-29 16:34:06 -07002501 sm->Pair = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002502 }
2503 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 0);
2504 wpa_remove_ptk(sm);
2505 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid, 0);
2506 sm->TimeoutCtr = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002507 if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
2508 sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP ||
2509 sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002510 wpa_auth_set_eapol(sm->wpa_auth, sm->addr,
2511 WPA_EAPOL_authorized, 0);
2512 }
2513}
2514
2515
2516SM_STATE(WPA_PTK, DISCONNECT)
2517{
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002518 u16 reason = sm->disconnect_reason;
2519
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002520 SM_ENTRY_MA(WPA_PTK, DISCONNECT, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07002521 sm->Disconnect = false;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002522 sm->disconnect_reason = 0;
2523 if (!reason)
2524 reason = WLAN_REASON_PREV_AUTH_NOT_VALID;
2525 wpa_sta_disconnect(sm->wpa_auth, sm->addr, reason);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002526}
2527
2528
2529SM_STATE(WPA_PTK, DISCONNECTED)
2530{
2531 SM_ENTRY_MA(WPA_PTK, DISCONNECTED, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07002532 sm->DeauthenticationRequest = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002533}
2534
2535
2536SM_STATE(WPA_PTK, AUTHENTICATION)
2537{
2538 SM_ENTRY_MA(WPA_PTK, AUTHENTICATION, wpa_ptk);
2539 os_memset(&sm->PTK, 0, sizeof(sm->PTK));
Hai Shalome21d4e82020-04-29 16:34:06 -07002540 sm->PTK_valid = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002541 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portControl_Auto,
2542 1);
2543 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 1);
Hai Shalome21d4e82020-04-29 16:34:06 -07002544 sm->AuthenticationRequest = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002545}
2546
2547
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002548static void wpa_group_ensure_init(struct wpa_authenticator *wpa_auth,
2549 struct wpa_group *group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002550{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002551 if (group->first_sta_seen)
2552 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002553 /*
2554 * System has run bit further than at the time hostapd was started
2555 * potentially very early during boot up. This provides better chances
2556 * of collecting more randomness on embedded systems. Re-initialize the
2557 * GMK and Counter here to improve their strength if there was not
2558 * enough entropy available immediately after system startup.
2559 */
Hai Shalomfdcde762020-04-02 11:19:20 -07002560 wpa_printf(MSG_DEBUG,
2561 "WPA: Re-initialize GMK/Counter on first station");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002562 if (random_pool_ready() != 1) {
Hai Shalomfdcde762020-04-02 11:19:20 -07002563 wpa_printf(MSG_INFO,
2564 "WPA: Not enough entropy in random pool to proceed - reject first 4-way handshake");
Hai Shalome21d4e82020-04-29 16:34:06 -07002565 group->reject_4way_hs_for_entropy = true;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002566 } else {
Hai Shalome21d4e82020-04-29 16:34:06 -07002567 group->first_sta_seen = true;
2568 group->reject_4way_hs_for_entropy = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002569 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002570
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002571 if (wpa_group_init_gmk_and_counter(wpa_auth, group) < 0 ||
2572 wpa_gtk_update(wpa_auth, group) < 0 ||
2573 wpa_group_config_group_keys(wpa_auth, group) < 0) {
2574 wpa_printf(MSG_INFO, "WPA: GMK/GTK setup failed");
Hai Shalome21d4e82020-04-29 16:34:06 -07002575 group->first_sta_seen = false;
2576 group->reject_4way_hs_for_entropy = true;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002577 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002578}
2579
2580
2581SM_STATE(WPA_PTK, AUTHENTICATION2)
2582{
2583 SM_ENTRY_MA(WPA_PTK, AUTHENTICATION2, wpa_ptk);
2584
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002585 wpa_group_ensure_init(sm->wpa_auth, sm->group);
Hai Shalome21d4e82020-04-29 16:34:06 -07002586 sm->ReAuthenticationRequest = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002587
Dmitry Shmidt04949592012-07-19 12:16:46 -07002588 /*
2589 * Definition of ANonce selection in IEEE Std 802.11i-2004 is somewhat
2590 * ambiguous. The Authenticator state machine uses a counter that is
2591 * incremented by one for each 4-way handshake. However, the security
2592 * analysis of 4-way handshake points out that unpredictable nonces
2593 * help in preventing precomputation attacks. Instead of the state
2594 * machine definition, use an unpredictable nonce value here to provide
2595 * stronger protection against potential precomputation attacks.
2596 */
2597 if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) {
Hai Shalomfdcde762020-04-02 11:19:20 -07002598 wpa_printf(MSG_ERROR,
2599 "WPA: Failed to get random data for ANonce.");
Hai Shalome21d4e82020-04-29 16:34:06 -07002600 sm->Disconnect = true;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002601 return;
2602 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002603 wpa_hexdump(MSG_DEBUG, "WPA: Assign ANonce", sm->ANonce,
2604 WPA_NONCE_LEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002605 /* IEEE 802.11i does not clear TimeoutCtr here, but this is more
2606 * logical place than INITIALIZE since AUTHENTICATION2 can be
2607 * re-entered on ReAuthenticationRequest without going through
2608 * INITIALIZE. */
2609 sm->TimeoutCtr = 0;
2610}
2611
2612
Jouni Malinen1420a892017-10-01 12:32:57 +03002613static int wpa_auth_sm_ptk_update(struct wpa_state_machine *sm)
2614{
2615 if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) {
2616 wpa_printf(MSG_ERROR,
2617 "WPA: Failed to get random data for ANonce");
Hai Shalome21d4e82020-04-29 16:34:06 -07002618 sm->Disconnect = true;
Jouni Malinen1420a892017-10-01 12:32:57 +03002619 return -1;
2620 }
2621 wpa_hexdump(MSG_DEBUG, "WPA: Assign new ANonce", sm->ANonce,
2622 WPA_NONCE_LEN);
2623 sm->TimeoutCtr = 0;
2624 return 0;
2625}
2626
2627
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002628SM_STATE(WPA_PTK, INITPMK)
2629{
2630 u8 msk[2 * PMK_LEN];
2631 size_t len = 2 * PMK_LEN;
2632
2633 SM_ENTRY_MA(WPA_PTK, INITPMK, wpa_ptk);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002634#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002635 sm->xxkey_len = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002636#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002637 if (sm->pmksa) {
2638 wpa_printf(MSG_DEBUG, "WPA: PMK from PMKSA cache");
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002639 os_memcpy(sm->PMK, sm->pmksa->pmk, sm->pmksa->pmk_len);
2640 sm->pmk_len = sm->pmksa->pmk_len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002641#ifdef CONFIG_DPP
2642 } else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP) {
2643 wpa_printf(MSG_DEBUG,
2644 "DPP: No PMKSA cache entry for STA - reject connection");
Hai Shalome21d4e82020-04-29 16:34:06 -07002645 sm->Disconnect = true;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002646 sm->disconnect_reason = WLAN_REASON_INVALID_PMKID;
2647 return;
2648#endif /* CONFIG_DPP */
Sunil Raviaf8751c2023-03-29 11:35:17 -07002649 } else if (wpa_auth_get_msk(sm->wpa_auth, wpa_auth_get_spa(sm),
2650 msk, &len) == 0) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002651 unsigned int pmk_len;
2652
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002653 if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002654 pmk_len = PMK_LEN_SUITE_B_192;
2655 else
2656 pmk_len = PMK_LEN;
Hai Shalomfdcde762020-04-02 11:19:20 -07002657 wpa_printf(MSG_DEBUG,
2658 "WPA: PMK from EAPOL state machine (MSK len=%zu PMK len=%u)",
2659 len, pmk_len);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002660 if (len < pmk_len) {
2661 wpa_printf(MSG_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07002662 "WPA: MSK not long enough (%zu) to create PMK (%u)",
2663 len, pmk_len);
Hai Shalome21d4e82020-04-29 16:34:06 -07002664 sm->Disconnect = true;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002665 return;
2666 }
2667 os_memcpy(sm->PMK, msk, pmk_len);
2668 sm->pmk_len = pmk_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002669#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002670 if (len >= 2 * PMK_LEN) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002671 if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) {
2672 os_memcpy(sm->xxkey, msk, SHA384_MAC_LEN);
2673 sm->xxkey_len = SHA384_MAC_LEN;
2674 } else {
2675 os_memcpy(sm->xxkey, msk + PMK_LEN, PMK_LEN);
2676 sm->xxkey_len = PMK_LEN;
2677 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002678 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002679#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002680 } else {
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002681 wpa_printf(MSG_DEBUG, "WPA: Could not get PMK, get_msk: %p",
Paul Stewart092955c2017-02-06 09:13:09 -08002682 sm->wpa_auth->cb->get_msk);
Hai Shalome21d4e82020-04-29 16:34:06 -07002683 sm->Disconnect = true;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002684 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002685 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002686 forced_memzero(msk, sizeof(msk));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002687
2688 sm->req_replay_counter_used = 0;
Hai Shalome21d4e82020-04-29 16:34:06 -07002689 /* IEEE 802.11i does not set keyRun to false, but not doing this
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002690 * will break reauthentication since EAPOL state machines may not be
2691 * get into AUTHENTICATING state that clears keyRun before WPA state
2692 * machine enters AUTHENTICATION2 state and goes immediately to INITPMK
2693 * state and takes PMK from the previously used AAA Key. This will
2694 * eventually fail in 4-Way Handshake because Supplicant uses PMK
Hai Shalome21d4e82020-04-29 16:34:06 -07002695 * derived from the new AAA Key. Setting keyRun = false here seems to
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002696 * be good workaround for this issue. */
Hai Shalome21d4e82020-04-29 16:34:06 -07002697 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyRun, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002698}
2699
2700
2701SM_STATE(WPA_PTK, INITPSK)
2702{
2703 const u8 *psk;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002704 size_t psk_len;
2705
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002706 SM_ENTRY_MA(WPA_PTK, INITPSK, wpa_ptk);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002707 psk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr, NULL,
Hai Shalom021b0b52019-04-10 11:17:58 -07002708 &psk_len, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002709 if (psk) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002710 os_memcpy(sm->PMK, psk, psk_len);
2711 sm->pmk_len = psk_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002712#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002713 sm->xxkey_len = PMK_LEN;
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002714#ifdef CONFIG_SAE
2715 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_SAE_EXT_KEY &&
2716 (psk_len == SHA512_MAC_LEN || psk_len == SHA384_MAC_LEN ||
2717 psk_len == SHA256_MAC_LEN))
2718 sm->xxkey_len = psk_len;
2719#endif /* CONFIG_SAE */
2720 os_memcpy(sm->xxkey, psk, sm->xxkey_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002721#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002722 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002723#ifdef CONFIG_SAE
2724 if (wpa_auth_uses_sae(sm) && sm->pmksa) {
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002725 wpa_printf(MSG_DEBUG, "SAE: PMK from PMKSA cache (len=%zu)",
2726 sm->pmksa->pmk_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002727 os_memcpy(sm->PMK, sm->pmksa->pmk, sm->pmksa->pmk_len);
2728 sm->pmk_len = sm->pmksa->pmk_len;
Hai Shalom021b0b52019-04-10 11:17:58 -07002729#ifdef CONFIG_IEEE80211R_AP
2730 os_memcpy(sm->xxkey, sm->pmksa->pmk, sm->pmksa->pmk_len);
2731 sm->xxkey_len = sm->pmksa->pmk_len;
2732#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002733 }
2734#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002735 sm->req_replay_counter_used = 0;
2736}
2737
2738
2739SM_STATE(WPA_PTK, PTKSTART)
2740{
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002741 u8 *buf;
2742 size_t buf_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002743 u8 *pmkid = NULL;
2744 size_t kde_len = 0;
Sunil8cd6f4d2022-06-28 18:40:46 +00002745 u16 key_info;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002746#ifdef CONFIG_TESTING_OPTIONS
2747 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
2748#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002749
2750 SM_ENTRY_MA(WPA_PTK, PTKSTART, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07002751 sm->PTKRequest = false;
2752 sm->TimeoutEvt = false;
2753 sm->alt_snonce_valid = false;
Sunil Ravia04bd252022-05-02 22:54:18 -07002754 sm->ptkstart_without_success++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002755
2756 sm->TimeoutCtr++;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002757 if (sm->TimeoutCtr > sm->wpa_auth->conf.wpa_pairwise_update_count) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002758 /* No point in sending the EAPOL-Key - we will disconnect
2759 * immediately following this. */
2760 return;
2761 }
2762
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002763#ifdef CONFIG_IEEE80211BE
2764 if (sm->mld_assoc_link_id >= 0)
2765 buf_len += 2 + RSN_SELECTOR_LEN + ETH_ALEN;
2766#endif /* CONFIG_IEEE80211BE */
2767#ifdef CONFIG_TESTING_OPTIONS
2768 if (conf->eapol_m1_elements)
2769 buf_len += wpabuf_len(conf->eapol_m1_elements);
2770#endif /* CONFIG_TESTING_OPTIONS */
2771
2772 buf = os_zalloc(buf_len);
2773 if (!buf)
2774 return;
2775
Sunil Raviaf8751c2023-03-29 11:35:17 -07002776 wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002777 "sending 1/4 msg of 4-Way Handshake");
2778 /*
Hai Shalomce48b4a2018-09-05 11:41:35 -07002779 * For infrastructure BSS cases, it is better for the AP not to include
2780 * the PMKID KDE in EAPOL-Key msg 1/4 since it could be used to initiate
2781 * offline search for the passphrase/PSK without having to be able to
2782 * capture a 4-way handshake from a STA that has access to the network.
2783 *
2784 * For IBSS cases, addition of PMKID KDE could be considered even with
2785 * WPA2-PSK cases that use multiple PSKs, but only if there is a single
2786 * possible PSK for this STA. However, this should not be done unless
2787 * there is support for using that information on the supplicant side.
2788 * The concern about exposing PMKID unnecessarily in infrastructure BSS
2789 * cases would also apply here, but at least in the IBSS case, this
2790 * would cover a potential real use case.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002791 */
2792 if (sm->wpa == WPA_VERSION_WPA2 &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002793 (wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) ||
2794 (sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE && sm->pmksa) ||
2795 wpa_key_mgmt_sae(sm->wpa_key_mgmt)) &&
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002796 sm->wpa_key_mgmt != WPA_KEY_MGMT_OSEN) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002797 pmkid = buf;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002798 kde_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002799 pmkid[0] = WLAN_EID_VENDOR_SPECIFIC;
2800 pmkid[1] = RSN_SELECTOR_LEN + PMKID_LEN;
2801 RSN_SELECTOR_PUT(&pmkid[2], RSN_KEY_DATA_PMKID);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002802 if (sm->pmksa) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002803 wpa_hexdump(MSG_DEBUG,
2804 "RSN: Message 1/4 PMKID from PMKSA entry",
2805 sm->pmksa->pmkid, PMKID_LEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002806 os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN],
2807 sm->pmksa->pmkid, PMKID_LEN);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002808 } else if (wpa_key_mgmt_suite_b(sm->wpa_key_mgmt)) {
2809 /* No KCK available to derive PMKID */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002810 wpa_printf(MSG_DEBUG,
2811 "RSN: No KCK available to derive PMKID for message 1/4");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002812 pmkid = NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -07002813#ifdef CONFIG_FILS
2814 } else if (wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
2815 if (sm->pmkid_set) {
2816 wpa_hexdump(MSG_DEBUG,
2817 "RSN: Message 1/4 PMKID from FILS/ERP",
2818 sm->pmkid, PMKID_LEN);
2819 os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN],
2820 sm->pmkid, PMKID_LEN);
2821 } else {
2822 /* No PMKID available */
2823 wpa_printf(MSG_DEBUG,
2824 "RSN: No FILS/ERP PMKID available for message 1/4");
2825 pmkid = NULL;
2826 }
2827#endif /* CONFIG_FILS */
2828#ifdef CONFIG_IEEE80211R_AP
2829 } else if (wpa_key_mgmt_ft(sm->wpa_key_mgmt) &&
2830 sm->ft_completed) {
2831 wpa_printf(MSG_DEBUG,
2832 "FT: No PMKID in message 1/4 when using FT protocol");
2833 pmkid = NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -07002834#endif /* CONFIG_IEEE80211R_AP */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002835#ifdef CONFIG_SAE
2836 } else if (wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
2837 if (sm->pmkid_set) {
2838 wpa_hexdump(MSG_DEBUG,
2839 "RSN: Message 1/4 PMKID from SAE",
2840 sm->pmkid, PMKID_LEN);
2841 os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN],
2842 sm->pmkid, PMKID_LEN);
2843 } else {
2844 /* No PMKID available */
2845 wpa_printf(MSG_DEBUG,
2846 "RSN: No SAE PMKID available for message 1/4");
2847 pmkid = NULL;
2848 }
2849#endif /* CONFIG_SAE */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002850 } else {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002851 /*
2852 * Calculate PMKID since no PMKSA cache entry was
2853 * available with pre-calculated PMKID.
2854 */
Sunil Raviaf8751c2023-03-29 11:35:17 -07002855 rsn_pmkid(sm->PMK, sm->pmk_len,
2856 wpa_auth_get_aa(sm),
2857 wpa_auth_get_spa(sm),
2858 &pmkid[2 + RSN_SELECTOR_LEN],
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002859 sm->wpa_key_mgmt);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002860 wpa_hexdump(MSG_DEBUG,
2861 "RSN: Message 1/4 PMKID derived from PMK",
2862 &pmkid[2 + RSN_SELECTOR_LEN], PMKID_LEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002863 }
2864 }
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002865 if (!pmkid)
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002866 kde_len = 0;
2867
2868#ifdef CONFIG_IEEE80211BE
2869 if (sm->mld_assoc_link_id >= 0) {
2870 wpa_printf(MSG_DEBUG,
2871 "RSN: MLD: Add MAC Address KDE: kde_len=%zu",
2872 kde_len);
2873 wpa_add_kde(buf + kde_len, RSN_KEY_DATA_MAC_ADDR,
Sunil Ravi7f769292024-07-23 22:21:32 +00002874 sm->wpa_auth->mld_addr, ETH_ALEN, NULL, 0);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002875 kde_len += 2 + RSN_SELECTOR_LEN + ETH_ALEN;
2876 }
2877#endif /* CONFIG_IEEE80211BE */
2878
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002879#ifdef CONFIG_TESTING_OPTIONS
2880 if (conf->eapol_m1_elements) {
2881 os_memcpy(buf + kde_len, wpabuf_head(conf->eapol_m1_elements),
2882 wpabuf_len(conf->eapol_m1_elements));
2883 kde_len += wpabuf_len(conf->eapol_m1_elements);
2884 }
2885#endif /* CONFIG_TESTING_OPTIONS */
2886
Sunil8cd6f4d2022-06-28 18:40:46 +00002887 key_info = WPA_KEY_INFO_ACK | WPA_KEY_INFO_KEY_TYPE;
2888 if (sm->pairwise_set && sm->wpa != WPA_VERSION_WPA)
2889 key_info |= WPA_KEY_INFO_SECURE;
2890 wpa_send_eapol(sm->wpa_auth, sm, key_info, NULL,
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002891 sm->ANonce, kde_len ? buf : NULL, kde_len, 0, 0);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002892 os_free(buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002893}
2894
2895
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002896static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002897 const u8 *pmk, unsigned int pmk_len,
Sunil Raviaf8751c2023-03-29 11:35:17 -07002898 struct wpa_ptk *ptk, int force_sha256,
2899 u8 *pmk_r0, u8 *pmk_r1, u8 *pmk_r0_name,
Sunil Ravi7f769292024-07-23 22:21:32 +00002900 size_t *key_len, bool no_kdk)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002901{
Hai Shalom021b0b52019-04-10 11:17:58 -07002902 const u8 *z = NULL;
Hai Shalom60840252021-02-19 19:02:11 -08002903 size_t z_len = 0, kdk_len;
Hai Shalomfdcde762020-04-02 11:19:20 -07002904 int akmp;
Sunil Ravi89eba102022-09-13 21:04:37 -07002905 int ret;
Hai Shalom021b0b52019-04-10 11:17:58 -07002906
Hai Shalom60840252021-02-19 19:02:11 -08002907 if (sm->wpa_auth->conf.force_kdk_derivation ||
Sunil Ravi7f769292024-07-23 22:21:32 +00002908 (!no_kdk && sm->wpa_auth->conf.secure_ltf &&
Hai Shaloma20dcd72022-02-04 13:43:00 -08002909 ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
Hai Shalom60840252021-02-19 19:02:11 -08002910 kdk_len = WPA_KDK_MAX_LEN;
2911 else
2912 kdk_len = 0;
2913
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002914#ifdef CONFIG_IEEE80211R_AP
Hai Shalom81f62d82019-07-22 12:10:00 -07002915 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
2916 if (sm->ft_completed) {
2917 u8 ptk_name[WPA_PMK_NAME_LEN];
2918
Sunil Ravi89eba102022-09-13 21:04:37 -07002919 ret = wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->pmk_r1_len,
2920 sm->SNonce, sm->ANonce,
Sunil Raviaf8751c2023-03-29 11:35:17 -07002921 wpa_auth_get_spa(sm),
2922 wpa_auth_get_aa(sm),
Sunil Ravi89eba102022-09-13 21:04:37 -07002923 sm->pmk_r1_name, ptk,
2924 ptk_name, sm->wpa_key_mgmt,
2925 sm->pairwise, kdk_len);
2926 } else {
Sunil Raviaf8751c2023-03-29 11:35:17 -07002927 ret = wpa_auth_derive_ptk_ft(sm, ptk, pmk_r0, pmk_r1,
2928 pmk_r0_name, key_len,
2929 kdk_len);
Hai Shalom81f62d82019-07-22 12:10:00 -07002930 }
Sunil Ravi89eba102022-09-13 21:04:37 -07002931 if (ret) {
2932 wpa_printf(MSG_ERROR, "FT: PTK derivation failed");
2933 return ret;
2934 }
2935
2936#ifdef CONFIG_PASN
Sunil Ravi7f769292024-07-23 22:21:32 +00002937 if (!no_kdk && sm->wpa_auth->conf.secure_ltf &&
Sunil Ravi89eba102022-09-13 21:04:37 -07002938 ieee802_11_rsnx_capab(sm->rsnxe,
2939 WLAN_RSNX_CAPAB_SECURE_LTF)) {
2940 ret = wpa_ltf_keyseed(ptk, sm->wpa_key_mgmt,
2941 sm->pairwise);
2942 if (ret) {
2943 wpa_printf(MSG_ERROR,
2944 "FT: LTF keyseed derivation failed");
2945 }
2946 }
2947#endif /* CONFIG_PASN */
2948 return ret;
Hai Shalom81f62d82019-07-22 12:10:00 -07002949 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002950#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002951
Hai Shalom021b0b52019-04-10 11:17:58 -07002952#ifdef CONFIG_DPP2
2953 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP && sm->dpp_z) {
2954 z = wpabuf_head(sm->dpp_z);
2955 z_len = wpabuf_len(sm->dpp_z);
2956 }
2957#endif /* CONFIG_DPP2 */
2958
Hai Shalomfdcde762020-04-02 11:19:20 -07002959 akmp = sm->wpa_key_mgmt;
2960 if (force_sha256)
2961 akmp |= WPA_KEY_MGMT_PSK_SHA256;
Sunil Ravi89eba102022-09-13 21:04:37 -07002962 ret = wpa_pmk_to_ptk(pmk, pmk_len, "Pairwise key expansion",
Sunil Raviaf8751c2023-03-29 11:35:17 -07002963 wpa_auth_get_aa(sm), wpa_auth_get_spa(sm),
2964 sm->ANonce, snonce, ptk, akmp,
2965 sm->pairwise, z, z_len, kdk_len);
Sunil Ravi89eba102022-09-13 21:04:37 -07002966 if (ret) {
2967 wpa_printf(MSG_DEBUG,
2968 "WPA: PTK derivation failed");
2969 return ret;
2970 }
2971
2972#ifdef CONFIG_PASN
Sunil Ravi7f769292024-07-23 22:21:32 +00002973 if (!no_kdk && sm->wpa_auth->conf.secure_ltf &&
Sunil Ravi89eba102022-09-13 21:04:37 -07002974 ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)) {
2975 ret = wpa_ltf_keyseed(ptk, sm->wpa_key_mgmt, sm->pairwise);
2976 if (ret) {
2977 wpa_printf(MSG_DEBUG,
2978 "WPA: LTF keyseed derivation failed");
2979 }
2980 }
2981#endif /* CONFIG_PASN */
2982 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002983}
2984
2985
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002986#ifdef CONFIG_FILS
2987
2988int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002989 size_t pmk_len, const u8 *snonce, const u8 *anonce,
2990 const u8 *dhss, size_t dhss_len,
2991 struct wpabuf *g_sta, struct wpabuf *g_ap)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002992{
2993 u8 ick[FILS_ICK_MAX_LEN];
2994 size_t ick_len;
2995 int res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002996 u8 fils_ft[FILS_FT_MAX_LEN];
Hai Shalom60840252021-02-19 19:02:11 -08002997 size_t fils_ft_len = 0, kdk_len;
2998
2999 if (sm->wpa_auth->conf.force_kdk_derivation ||
3000 (sm->wpa_auth->conf.secure_ltf &&
Hai Shaloma20dcd72022-02-04 13:43:00 -08003001 ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
Hai Shalom60840252021-02-19 19:02:11 -08003002 kdk_len = WPA_KDK_MAX_LEN;
3003 else
3004 kdk_len = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003005
Sunil Raviaf8751c2023-03-29 11:35:17 -07003006 res = fils_pmk_to_ptk(pmk, pmk_len, wpa_auth_get_spa(sm),
3007 wpa_auth_get_aa(sm),
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003008 snonce, anonce, dhss, dhss_len,
3009 &sm->PTK, ick, &ick_len,
3010 sm->wpa_key_mgmt, sm->pairwise,
Hai Shalom60840252021-02-19 19:02:11 -08003011 fils_ft, &fils_ft_len, kdk_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003012 if (res < 0)
3013 return res;
Sunil Ravi89eba102022-09-13 21:04:37 -07003014
3015#ifdef CONFIG_PASN
3016 if (sm->wpa_auth->conf.secure_ltf &&
3017 ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)) {
3018 res = wpa_ltf_keyseed(&sm->PTK, sm->wpa_key_mgmt, sm->pairwise);
3019 if (res) {
3020 wpa_printf(MSG_ERROR,
3021 "FILS: LTF keyseed derivation failed");
3022 return res;
3023 }
3024 }
3025#endif /* CONFIG_PASN */
3026
Hai Shalome21d4e82020-04-29 16:34:06 -07003027 sm->PTK_valid = true;
3028 sm->tk_already_set = false;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003029
3030#ifdef CONFIG_IEEE80211R_AP
3031 if (fils_ft_len) {
3032 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
3033 struct wpa_auth_config *conf = &wpa_auth->conf;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003034 u8 pmk_r0[PMK_LEN_MAX], pmk_r0_name[WPA_PMK_NAME_LEN];
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003035
3036 if (wpa_derive_pmk_r0(fils_ft, fils_ft_len,
3037 conf->ssid, conf->ssid_len,
3038 conf->mobility_domain,
3039 conf->r0_key_holder,
3040 conf->r0_key_holder_len,
Sunil Raviaf8751c2023-03-29 11:35:17 -07003041 wpa_auth_get_spa(sm), pmk_r0, pmk_r0_name,
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00003042 sm->wpa_key_mgmt) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003043 return -1;
3044
Roshan Pius3a1667e2018-07-03 15:17:14 -07003045 wpa_ft_store_pmk_fils(sm, pmk_r0, pmk_r0_name);
Hai Shalom81f62d82019-07-22 12:10:00 -07003046 forced_memzero(fils_ft, sizeof(fils_ft));
Hai Shalom021b0b52019-04-10 11:17:58 -07003047
3048 res = wpa_derive_pmk_r1_name(pmk_r0_name, conf->r1_key_holder,
Sunil Raviaf8751c2023-03-29 11:35:17 -07003049 wpa_auth_get_spa(sm),
3050 sm->pmk_r1_name,
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00003051 fils_ft_len);
Hai Shalom81f62d82019-07-22 12:10:00 -07003052 forced_memzero(pmk_r0, PMK_LEN_MAX);
Hai Shalom021b0b52019-04-10 11:17:58 -07003053 if (res < 0)
3054 return -1;
3055 wpa_hexdump(MSG_DEBUG, "FILS+FT: PMKR1Name", sm->pmk_r1_name,
3056 WPA_PMK_NAME_LEN);
3057 sm->pmk_r1_name_valid = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003058 }
3059#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003060
3061 res = fils_key_auth_sk(ick, ick_len, snonce, anonce,
Sunil Raviaf8751c2023-03-29 11:35:17 -07003062 wpa_auth_get_spa(sm),
3063 wpa_auth_get_aa(sm),
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003064 g_sta ? wpabuf_head(g_sta) : NULL,
3065 g_sta ? wpabuf_len(g_sta) : 0,
3066 g_ap ? wpabuf_head(g_ap) : NULL,
3067 g_ap ? wpabuf_len(g_ap) : 0,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003068 sm->wpa_key_mgmt, sm->fils_key_auth_sta,
3069 sm->fils_key_auth_ap,
3070 &sm->fils_key_auth_len);
Hai Shalom81f62d82019-07-22 12:10:00 -07003071 forced_memzero(ick, sizeof(ick));
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003072
3073 /* Store nonces for (Re)Association Request/Response frame processing */
3074 os_memcpy(sm->SNonce, snonce, FILS_NONCE_LEN);
3075 os_memcpy(sm->ANonce, anonce, FILS_NONCE_LEN);
3076
3077 return res;
3078}
3079
3080
3081static int wpa_aead_decrypt(struct wpa_state_machine *sm, struct wpa_ptk *ptk,
3082 u8 *buf, size_t buf_len, u16 *_key_data_len)
3083{
3084 struct ieee802_1x_hdr *hdr;
3085 struct wpa_eapol_key *key;
3086 u8 *pos;
3087 u16 key_data_len;
3088 u8 *tmp;
3089 const u8 *aad[1];
3090 size_t aad_len[1];
3091
3092 hdr = (struct ieee802_1x_hdr *) buf;
3093 key = (struct wpa_eapol_key *) (hdr + 1);
3094 pos = (u8 *) (key + 1);
3095 key_data_len = WPA_GET_BE16(pos);
3096 if (key_data_len < AES_BLOCK_SIZE ||
3097 key_data_len > buf_len - sizeof(*hdr) - sizeof(*key) - 2) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07003098 wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003099 "No room for AES-SIV data in the frame");
3100 return -1;
3101 }
3102 pos += 2; /* Pointing at the Encrypted Key Data field */
3103
3104 tmp = os_malloc(key_data_len);
3105 if (!tmp)
3106 return -1;
3107
3108 /* AES-SIV AAD from EAPOL protocol version field (inclusive) to
3109 * to Key Data (exclusive). */
3110 aad[0] = buf;
3111 aad_len[0] = pos - buf;
3112 if (aes_siv_decrypt(ptk->kek, ptk->kek_len, pos, key_data_len,
3113 1, aad, aad_len, tmp) < 0) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07003114 wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003115 "Invalid AES-SIV data in the frame");
3116 bin_clear_free(tmp, key_data_len);
3117 return -1;
3118 }
3119
3120 /* AEAD decryption and validation completed successfully */
3121 key_data_len -= AES_BLOCK_SIZE;
3122 wpa_hexdump_key(MSG_DEBUG, "WPA: Decrypted Key Data",
3123 tmp, key_data_len);
3124
3125 /* Replace Key Data field with the decrypted version */
3126 os_memcpy(pos, tmp, key_data_len);
3127 pos -= 2; /* Key Data Length field */
3128 WPA_PUT_BE16(pos, key_data_len);
3129 bin_clear_free(tmp, key_data_len);
3130 if (_key_data_len)
3131 *_key_data_len = key_data_len;
3132 return 0;
3133}
3134
3135
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003136const u8 * wpa_fils_validate_fils_session(struct wpa_state_machine *sm,
3137 const u8 *ies, size_t ies_len,
3138 const u8 *fils_session)
3139{
3140 const u8 *ie, *end;
3141 const u8 *session = NULL;
3142
3143 if (!wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
3144 wpa_printf(MSG_DEBUG,
3145 "FILS: Not a FILS AKM - reject association");
3146 return NULL;
3147 }
3148
3149 /* Verify Session element */
3150 ie = ies;
3151 end = ((const u8 *) ie) + ies_len;
3152 while (ie + 1 < end) {
3153 if (ie + 2 + ie[1] > end)
3154 break;
3155 if (ie[0] == WLAN_EID_EXTENSION &&
3156 ie[1] >= 1 + FILS_SESSION_LEN &&
3157 ie[2] == WLAN_EID_EXT_FILS_SESSION) {
3158 session = ie;
3159 break;
3160 }
3161 ie += 2 + ie[1];
3162 }
3163
3164 if (!session) {
3165 wpa_printf(MSG_DEBUG,
3166 "FILS: %s: Could not find FILS Session element in Assoc Req - reject",
3167 __func__);
3168 return NULL;
3169 }
3170
3171 if (!fils_session) {
3172 wpa_printf(MSG_DEBUG,
3173 "FILS: %s: Could not find FILS Session element in STA entry - reject",
3174 __func__);
3175 return NULL;
3176 }
3177
3178 if (os_memcmp(fils_session, session + 3, FILS_SESSION_LEN) != 0) {
3179 wpa_printf(MSG_DEBUG, "FILS: Session mismatch");
3180 wpa_hexdump(MSG_DEBUG, "FILS: Expected FILS Session",
3181 fils_session, FILS_SESSION_LEN);
3182 wpa_hexdump(MSG_DEBUG, "FILS: Received FILS Session",
3183 session + 3, FILS_SESSION_LEN);
3184 return NULL;
3185 }
3186 return session;
3187}
3188
3189
3190int wpa_fils_validate_key_confirm(struct wpa_state_machine *sm, const u8 *ies,
3191 size_t ies_len)
3192{
3193 struct ieee802_11_elems elems;
3194
3195 if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed) {
3196 wpa_printf(MSG_DEBUG,
3197 "FILS: Failed to parse decrypted elements");
3198 return -1;
3199 }
3200
3201 if (!elems.fils_session) {
3202 wpa_printf(MSG_DEBUG, "FILS: No FILS Session element");
3203 return -1;
3204 }
3205
3206 if (!elems.fils_key_confirm) {
3207 wpa_printf(MSG_DEBUG, "FILS: No FILS Key Confirm element");
3208 return -1;
3209 }
3210
3211 if (elems.fils_key_confirm_len != sm->fils_key_auth_len) {
3212 wpa_printf(MSG_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07003213 "FILS: Unexpected Key-Auth length %d (expected %zu)",
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003214 elems.fils_key_confirm_len,
Hai Shalomfdcde762020-04-02 11:19:20 -07003215 sm->fils_key_auth_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003216 return -1;
3217 }
3218
3219 if (os_memcmp(elems.fils_key_confirm, sm->fils_key_auth_sta,
3220 sm->fils_key_auth_len) != 0) {
3221 wpa_printf(MSG_DEBUG, "FILS: Key-Auth mismatch");
3222 wpa_hexdump(MSG_DEBUG, "FILS: Received Key-Auth",
3223 elems.fils_key_confirm, elems.fils_key_confirm_len);
3224 wpa_hexdump(MSG_DEBUG, "FILS: Expected Key-Auth",
3225 sm->fils_key_auth_sta, sm->fils_key_auth_len);
3226 return -1;
3227 }
3228
3229 return 0;
3230}
3231
3232
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003233int fils_decrypt_assoc(struct wpa_state_machine *sm, const u8 *fils_session,
3234 const struct ieee80211_mgmt *mgmt, size_t frame_len,
3235 u8 *pos, size_t left)
3236{
3237 u16 fc, stype;
3238 const u8 *end, *ie_start, *ie, *session, *crypt;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003239 const u8 *aad[5];
3240 size_t aad_len[5];
3241
3242 if (!sm || !sm->PTK_valid) {
3243 wpa_printf(MSG_DEBUG,
3244 "FILS: No KEK to decrypt Assocication Request frame");
3245 return -1;
3246 }
3247
3248 if (!wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
3249 wpa_printf(MSG_DEBUG,
3250 "FILS: Not a FILS AKM - reject association");
3251 return -1;
3252 }
3253
3254 end = ((const u8 *) mgmt) + frame_len;
3255 fc = le_to_host16(mgmt->frame_control);
3256 stype = WLAN_FC_GET_STYPE(fc);
3257 if (stype == WLAN_FC_STYPE_REASSOC_REQ)
3258 ie_start = mgmt->u.reassoc_req.variable;
3259 else
3260 ie_start = mgmt->u.assoc_req.variable;
3261 ie = ie_start;
3262
3263 /*
3264 * Find FILS Session element which is the last unencrypted element in
3265 * the frame.
3266 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003267 session = wpa_fils_validate_fils_session(sm, ie, end - ie,
3268 fils_session);
3269 if (!session) {
3270 wpa_printf(MSG_DEBUG, "FILS: Session validation failed");
3271 return -1;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003272 }
3273
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003274 crypt = session + 2 + session[1];
3275
3276 if (end - crypt < AES_BLOCK_SIZE) {
3277 wpa_printf(MSG_DEBUG,
3278 "FILS: Too short frame to include AES-SIV data");
3279 return -1;
3280 }
3281
3282 /* AES-SIV AAD vectors */
3283
3284 /* The STA's MAC address */
3285 aad[0] = mgmt->sa;
3286 aad_len[0] = ETH_ALEN;
3287 /* The AP's BSSID */
3288 aad[1] = mgmt->da;
3289 aad_len[1] = ETH_ALEN;
3290 /* The STA's nonce */
3291 aad[2] = sm->SNonce;
3292 aad_len[2] = FILS_NONCE_LEN;
3293 /* The AP's nonce */
3294 aad[3] = sm->ANonce;
3295 aad_len[3] = FILS_NONCE_LEN;
3296 /*
3297 * The (Re)Association Request frame from the Capability Information
3298 * field to the FILS Session element (both inclusive).
3299 */
3300 aad[4] = (const u8 *) &mgmt->u.assoc_req.capab_info;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003301 aad_len[4] = crypt - aad[4];
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003302
3303 if (aes_siv_decrypt(sm->PTK.kek, sm->PTK.kek_len, crypt, end - crypt,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003304 5, aad, aad_len, pos + (crypt - ie_start)) < 0) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003305 wpa_printf(MSG_DEBUG,
3306 "FILS: Invalid AES-SIV data in the frame");
3307 return -1;
3308 }
3309 wpa_hexdump(MSG_DEBUG, "FILS: Decrypted Association Request elements",
3310 pos, left - AES_BLOCK_SIZE);
3311
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003312 if (wpa_fils_validate_key_confirm(sm, pos, left - AES_BLOCK_SIZE) < 0) {
3313 wpa_printf(MSG_DEBUG, "FILS: Key Confirm validation failed");
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003314 return -1;
3315 }
3316
3317 return left - AES_BLOCK_SIZE;
3318}
3319
3320
3321int fils_encrypt_assoc(struct wpa_state_machine *sm, u8 *buf,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003322 size_t current_len, size_t max_len,
3323 const struct wpabuf *hlp)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003324{
3325 u8 *end = buf + max_len;
3326 u8 *pos = buf + current_len;
3327 struct ieee80211_mgmt *mgmt;
3328 struct wpabuf *plain;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003329 const u8 *aad[5];
3330 size_t aad_len[5];
3331
3332 if (!sm || !sm->PTK_valid)
3333 return -1;
3334
3335 wpa_hexdump(MSG_DEBUG,
3336 "FILS: Association Response frame before FILS processing",
3337 buf, current_len);
3338
3339 mgmt = (struct ieee80211_mgmt *) buf;
3340
3341 /* AES-SIV AAD vectors */
3342
3343 /* The AP's BSSID */
3344 aad[0] = mgmt->sa;
3345 aad_len[0] = ETH_ALEN;
3346 /* The STA's MAC address */
3347 aad[1] = mgmt->da;
3348 aad_len[1] = ETH_ALEN;
3349 /* The AP's nonce */
3350 aad[2] = sm->ANonce;
3351 aad_len[2] = FILS_NONCE_LEN;
3352 /* The STA's nonce */
3353 aad[3] = sm->SNonce;
3354 aad_len[3] = FILS_NONCE_LEN;
3355 /*
3356 * The (Re)Association Response frame from the Capability Information
3357 * field (the same offset in both Association and Reassociation
3358 * Response frames) to the FILS Session element (both inclusive).
3359 */
3360 aad[4] = (const u8 *) &mgmt->u.assoc_resp.capab_info;
3361 aad_len[4] = pos - aad[4];
3362
3363 /* The following elements will be encrypted with AES-SIV */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003364 plain = fils_prepare_plainbuf(sm, hlp);
3365 if (!plain) {
3366 wpa_printf(MSG_DEBUG, "FILS: Plain buffer prep failed");
3367 return -1;
3368 }
3369
3370 if (pos + wpabuf_len(plain) + AES_BLOCK_SIZE > end) {
3371 wpa_printf(MSG_DEBUG,
3372 "FILS: Not enough room for FILS elements");
Hai Shalom81f62d82019-07-22 12:10:00 -07003373 wpabuf_clear_free(plain);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003374 return -1;
3375 }
3376
3377 wpa_hexdump_buf_key(MSG_DEBUG, "FILS: Association Response plaintext",
3378 plain);
3379
3380 if (aes_siv_encrypt(sm->PTK.kek, sm->PTK.kek_len,
3381 wpabuf_head(plain), wpabuf_len(plain),
3382 5, aad, aad_len, pos) < 0) {
Hai Shalom81f62d82019-07-22 12:10:00 -07003383 wpabuf_clear_free(plain);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003384 return -1;
3385 }
3386
3387 wpa_hexdump(MSG_DEBUG,
3388 "FILS: Encrypted Association Response elements",
3389 pos, AES_BLOCK_SIZE + wpabuf_len(plain));
3390 current_len += wpabuf_len(plain) + AES_BLOCK_SIZE;
Hai Shalom81f62d82019-07-22 12:10:00 -07003391 wpabuf_clear_free(plain);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003392
3393 sm->fils_completed = 1;
3394
3395 return current_len;
3396}
3397
3398
3399static struct wpabuf * fils_prepare_plainbuf(struct wpa_state_machine *sm,
3400 const struct wpabuf *hlp)
3401{
3402 struct wpabuf *plain;
3403 u8 *len, *tmp, *tmp2;
3404 u8 hdr[2];
Hai Shaloma20dcd72022-02-04 13:43:00 -08003405 u8 *gtk, stub_gtk[32];
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003406 size_t gtk_len;
3407 struct wpa_group *gsm;
Hai Shalomfdcde762020-04-02 11:19:20 -07003408 size_t plain_len;
3409 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003410
Hai Shalomfdcde762020-04-02 11:19:20 -07003411 plain_len = 1000 + ieee80211w_kde_len(sm);
3412 if (conf->transition_disable)
3413 plain_len += 2 + RSN_SELECTOR_LEN + 1;
3414 plain = wpabuf_alloc(plain_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003415 if (!plain)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003416 return NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003417
3418 /* TODO: FILS Public Key */
3419
3420 /* FILS Key Confirmation */
3421 wpabuf_put_u8(plain, WLAN_EID_EXTENSION); /* Element ID */
3422 wpabuf_put_u8(plain, 1 + sm->fils_key_auth_len); /* Length */
3423 /* Element ID Extension */
3424 wpabuf_put_u8(plain, WLAN_EID_EXT_FILS_KEY_CONFIRM);
3425 wpabuf_put_data(plain, sm->fils_key_auth_ap, sm->fils_key_auth_len);
3426
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003427 /* FILS HLP Container */
3428 if (hlp)
3429 wpabuf_put_buf(plain, hlp);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003430
3431 /* TODO: FILS IP Address Assignment */
3432
3433 /* Key Delivery */
3434 gsm = sm->group;
3435 wpabuf_put_u8(plain, WLAN_EID_EXTENSION); /* Element ID */
3436 len = wpabuf_put(plain, 1);
3437 wpabuf_put_u8(plain, WLAN_EID_EXT_KEY_DELIVERY);
3438 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN,
3439 wpabuf_put(plain, WPA_KEY_RSC_LEN));
3440 /* GTK KDE */
3441 gtk = gsm->GTK[gsm->GN - 1];
3442 gtk_len = gsm->GTK_len;
Hai Shalomfdcde762020-04-02 11:19:20 -07003443 if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003444 /*
3445 * Provide unique random GTK to each STA to prevent use
3446 * of GTK in the BSS.
3447 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003448 if (random_get_bytes(stub_gtk, gtk_len) < 0) {
Hai Shalom81f62d82019-07-22 12:10:00 -07003449 wpabuf_clear_free(plain);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003450 return NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003451 }
Hai Shaloma20dcd72022-02-04 13:43:00 -08003452 gtk = stub_gtk;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003453 }
3454 hdr[0] = gsm->GN & 0x03;
3455 hdr[1] = 0;
3456 tmp = wpabuf_put(plain, 0);
3457 tmp2 = wpa_add_kde(tmp, RSN_KEY_DATA_GROUPKEY, hdr, 2,
3458 gtk, gtk_len);
3459 wpabuf_put(plain, tmp2 - tmp);
3460
Hai Shalomfdcde762020-04-02 11:19:20 -07003461 /* IGTK KDE and BIGTK KDE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003462 tmp = wpabuf_put(plain, 0);
3463 tmp2 = ieee80211w_kde_add(sm, tmp);
3464 wpabuf_put(plain, tmp2 - tmp);
3465
Hai Shalomfdcde762020-04-02 11:19:20 -07003466 if (conf->transition_disable) {
3467 tmp = wpabuf_put(plain, 0);
3468 tmp2 = wpa_add_kde(tmp, WFA_KEY_DATA_TRANSITION_DISABLE,
3469 &conf->transition_disable, 1, NULL, 0);
3470 wpabuf_put(plain, tmp2 - tmp);
3471 }
3472
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003473 *len = (u8 *) wpabuf_put(plain, 0) - len - 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08003474
3475#ifdef CONFIG_OCV
3476 if (wpa_auth_uses_ocv(sm)) {
3477 struct wpa_channel_info ci;
3478 u8 *pos;
3479
3480 if (wpa_channel_info(sm->wpa_auth, &ci) != 0) {
3481 wpa_printf(MSG_WARNING,
3482 "FILS: Failed to get channel info for OCI element");
Hai Shalom81f62d82019-07-22 12:10:00 -07003483 wpabuf_clear_free(plain);
Hai Shalom74f70d42019-02-11 14:42:39 -08003484 return NULL;
3485 }
Hai Shalom899fcc72020-10-19 14:38:18 -07003486#ifdef CONFIG_TESTING_OPTIONS
3487 if (conf->oci_freq_override_fils_assoc) {
3488 wpa_printf(MSG_INFO,
3489 "TEST: Override OCI frequency %d -> %u MHz",
3490 ci.frequency,
3491 conf->oci_freq_override_fils_assoc);
3492 ci.frequency = conf->oci_freq_override_fils_assoc;
3493 }
3494#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom74f70d42019-02-11 14:42:39 -08003495
3496 pos = wpabuf_put(plain, OCV_OCI_EXTENDED_LEN);
3497 if (ocv_insert_extended_oci(&ci, pos) < 0) {
Hai Shalom81f62d82019-07-22 12:10:00 -07003498 wpabuf_clear_free(plain);
Hai Shalom74f70d42019-02-11 14:42:39 -08003499 return NULL;
3500 }
3501 }
3502#endif /* CONFIG_OCV */
3503
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003504 return plain;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003505}
3506
3507
3508int fils_set_tk(struct wpa_state_machine *sm)
3509{
3510 enum wpa_alg alg;
3511 int klen;
3512
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003513 if (!sm || !sm->PTK_valid) {
3514 wpa_printf(MSG_DEBUG, "FILS: No valid PTK available to set TK");
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003515 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003516 }
3517 if (sm->tk_already_set) {
3518 wpa_printf(MSG_DEBUG, "FILS: TK already set to the driver");
3519 return -1;
3520 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003521
3522 alg = wpa_cipher_to_alg(sm->pairwise);
3523 klen = wpa_cipher_key_len(sm->pairwise);
3524
3525 wpa_printf(MSG_DEBUG, "FILS: Configure TK to the driver");
3526 if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0,
Hai Shalomfdcde762020-04-02 11:19:20 -07003527 sm->PTK.tk, klen, KEY_FLAG_PAIRWISE_RX_TX)) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003528 wpa_printf(MSG_DEBUG, "FILS: Failed to set TK to the driver");
3529 return -1;
3530 }
Sunil Ravi89eba102022-09-13 21:04:37 -07003531
3532#ifdef CONFIG_PASN
3533 if (sm->wpa_auth->conf.secure_ltf &&
3534 ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF) &&
3535 wpa_auth_set_ltf_keyseed(sm->wpa_auth, sm->addr,
3536 sm->PTK.ltf_keyseed,
3537 sm->PTK.ltf_keyseed_len)) {
3538 wpa_printf(MSG_ERROR,
3539 "FILS: Failed to set LTF keyseed to driver");
3540 return -1;
3541 }
3542#endif /* CONFIG_PASN */
3543
Sunil8cd6f4d2022-06-28 18:40:46 +00003544 sm->pairwise_set = true;
Hai Shalome21d4e82020-04-29 16:34:06 -07003545 sm->tk_already_set = true;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003546
Hai Shalom60840252021-02-19 19:02:11 -08003547 wpa_auth_store_ptksa(sm->wpa_auth, sm->addr, sm->pairwise,
3548 dot11RSNAConfigPMKLifetime, &sm->PTK);
3549
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003550 return 0;
3551}
3552
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003553
3554u8 * hostapd_eid_assoc_fils_session(struct wpa_state_machine *sm, u8 *buf,
3555 const u8 *fils_session, struct wpabuf *hlp)
3556{
3557 struct wpabuf *plain;
3558 u8 *pos = buf;
3559
3560 /* FILS Session */
3561 *pos++ = WLAN_EID_EXTENSION; /* Element ID */
3562 *pos++ = 1 + FILS_SESSION_LEN; /* Length */
3563 *pos++ = WLAN_EID_EXT_FILS_SESSION; /* Element ID Extension */
3564 os_memcpy(pos, fils_session, FILS_SESSION_LEN);
3565 pos += FILS_SESSION_LEN;
3566
3567 plain = fils_prepare_plainbuf(sm, hlp);
3568 if (!plain) {
3569 wpa_printf(MSG_DEBUG, "FILS: Plain buffer prep failed");
3570 return NULL;
3571 }
3572
3573 os_memcpy(pos, wpabuf_head(plain), wpabuf_len(plain));
3574 pos += wpabuf_len(plain);
3575
Hai Shalomfdcde762020-04-02 11:19:20 -07003576 wpa_printf(MSG_DEBUG, "%s: plain buf_len: %zu", __func__,
3577 wpabuf_len(plain));
Hai Shalom81f62d82019-07-22 12:10:00 -07003578 wpabuf_clear_free(plain);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003579 sm->fils_completed = 1;
3580 return pos;
3581}
3582
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003583#endif /* CONFIG_FILS */
3584
3585
Hai Shalom74f70d42019-02-11 14:42:39 -08003586#ifdef CONFIG_OCV
3587int get_sta_tx_parameters(struct wpa_state_machine *sm, int ap_max_chanwidth,
3588 int ap_seg1_idx, int *bandwidth, int *seg1_idx)
3589{
3590 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
3591
3592 if (!wpa_auth->cb->get_sta_tx_params)
3593 return -1;
3594 return wpa_auth->cb->get_sta_tx_params(wpa_auth->cb_ctx, sm->addr,
3595 ap_max_chanwidth, ap_seg1_idx,
3596 bandwidth, seg1_idx);
3597}
3598#endif /* CONFIG_OCV */
3599
3600
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003601static int wpa_auth_validate_ml_kdes_m2(struct wpa_state_machine *sm,
3602 struct wpa_eapol_ie_parse *kde)
3603{
3604#ifdef CONFIG_IEEE80211BE
3605 int i;
3606 unsigned int n_links = 0;
3607
3608 if (sm->mld_assoc_link_id < 0)
3609 return 0;
3610
3611 /* MLD MAC address must be the same */
3612 if (!kde->mac_addr ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003613 !ether_addr_equal(kde->mac_addr, sm->peer_mld_addr)) {
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003614 wpa_printf(MSG_DEBUG, "RSN: MLD: Invalid MLD address");
3615 return -1;
3616 }
3617
3618 /* Find matching link ID and the MAC address for each link */
Sunil Ravi99c035e2024-07-12 01:42:03 +00003619 for_each_link(kde->valid_mlo_links, i) {
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003620 /*
3621 * Each entry should contain the link information and the MAC
3622 * address.
3623 */
3624 if (kde->mlo_link_len[i] != 1 + ETH_ALEN) {
3625 wpa_printf(MSG_DEBUG,
3626 "RSN: MLD: Invalid MLO Link (ID %u) KDE len=%zu",
3627 i, kde->mlo_link_len[i]);
3628 return -1;
3629 }
3630
3631 if (!sm->mld_links[i].valid || i == sm->mld_assoc_link_id) {
3632 wpa_printf(MSG_DEBUG,
3633 "RSN: MLD: Invalid link ID=%u", i);
3634 return -1;
3635 }
3636
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003637 if (!ether_addr_equal(sm->mld_links[i].peer_addr,
3638 kde->mlo_link[i] + 1)) {
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003639 wpa_printf(MSG_DEBUG,
3640 "RSN: MLD: invalid MAC address=" MACSTR
3641 " expected " MACSTR " (link ID %u)",
3642 MAC2STR(kde->mlo_link[i] + 1),
3643 MAC2STR(sm->mld_links[i].peer_addr), i);
3644 return -1;
3645 }
3646
3647 n_links++;
3648 }
3649
3650 /* Must have the same number of MLO links (excluding the local one) */
3651 if (n_links != sm->n_mld_affiliated_links) {
3652 wpa_printf(MSG_DEBUG,
3653 "RSN: MLD: Expecting %u MLD links in msg 2, but got %u",
3654 sm->n_mld_affiliated_links, n_links);
3655 return -1;
3656 }
3657#endif /* CONFIG_IEEE80211BE */
3658
3659 return 0;
3660}
3661
3662
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003663SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
3664{
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003665 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003666 struct wpa_ptk PTK;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07003667 int ok = 0, psk_found = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003668 const u8 *pmk = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003669 size_t pmk_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003670 int ft;
3671 const u8 *eapol_key_ie, *key_data, *mic;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003672 u16 key_info, ver, key_data_length;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003673 size_t mic_len, eapol_key_ie_len;
3674 struct ieee802_1x_hdr *hdr;
3675 struct wpa_eapol_key *key;
3676 struct wpa_eapol_ie_parse kde;
Hai Shalom021b0b52019-04-10 11:17:58 -07003677 int vlan_id = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003678 int owe_ptk_workaround = !!wpa_auth->conf.owe_ptk_workaround;
Sunil Raviaf8751c2023-03-29 11:35:17 -07003679 u8 pmk_r0[PMK_LEN_MAX], pmk_r0_name[WPA_PMK_NAME_LEN];
3680 u8 pmk_r1[PMK_LEN_MAX];
3681 size_t key_len;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003682 u8 *key_data_buf = NULL;
3683 size_t key_data_buf_len = 0;
Sunil Ravi7f769292024-07-23 22:21:32 +00003684 bool derive_kdk, no_kdk = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003685
3686 SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07003687 sm->EAPOLKeyReceived = false;
3688 sm->update_snonce = false;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003689 os_memset(&PTK, 0, sizeof(PTK));
3690
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003691 mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003692
Sunil Ravi7f769292024-07-23 22:21:32 +00003693 derive_kdk = sm->wpa_auth->conf.secure_ltf &&
3694 ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF);
3695
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003696 /* WPA with IEEE 802.1X: use the derived PMK from EAP
3697 * WPA-PSK: iterate through possible PSKs and select the one matching
3698 * the packet */
3699 for (;;) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003700 if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
3701 !wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07003702 pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr,
Hai Shalom021b0b52019-04-10 11:17:58 -07003703 sm->p2p_dev_addr, pmk, &pmk_len,
3704 &vlan_id);
Hai Shalomfdcde762020-04-02 11:19:20 -07003705 if (!pmk)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003706 break;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07003707 psk_found = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003708#ifdef CONFIG_IEEE80211R_AP
3709 if (wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) {
3710 os_memcpy(sm->xxkey, pmk, pmk_len);
3711 sm->xxkey_len = pmk_len;
3712 }
3713#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003714 } else {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003715 pmk = sm->PMK;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003716 pmk_len = sm->pmk_len;
3717 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003718
Hai Shalom81f62d82019-07-22 12:10:00 -07003719 if ((!pmk || !pmk_len) && sm->pmksa) {
3720 wpa_printf(MSG_DEBUG, "WPA: Use PMK from PMKSA cache");
3721 pmk = sm->pmksa->pmk;
3722 pmk_len = sm->pmksa->pmk_len;
3723 }
3724
Sunil Ravi7f769292024-07-23 22:21:32 +00003725 no_kdk = false;
3726 try_without_kdk:
Hai Shalomfdcde762020-04-02 11:19:20 -07003727 if (wpa_derive_ptk(sm, sm->SNonce, pmk, pmk_len, &PTK,
Sunil Raviaf8751c2023-03-29 11:35:17 -07003728 owe_ptk_workaround == 2, pmk_r0, pmk_r1,
Sunil Ravi7f769292024-07-23 22:21:32 +00003729 pmk_r0_name, &key_len, no_kdk) < 0)
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003730 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003731
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003732 if (mic_len &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003733 wpa_verify_key_mic(sm->wpa_key_mgmt, pmk_len, &PTK,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003734 sm->last_rx_eapol_key,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003735 sm->last_rx_eapol_key_len) == 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07003736 if (sm->PMK != pmk) {
3737 os_memcpy(sm->PMK, pmk, pmk_len);
3738 sm->pmk_len = pmk_len;
3739 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003740 ok = 1;
3741 break;
3742 }
3743
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003744#ifdef CONFIG_FILS
3745 if (!mic_len &&
3746 wpa_aead_decrypt(sm, &PTK, sm->last_rx_eapol_key,
3747 sm->last_rx_eapol_key_len, NULL) == 0) {
3748 ok = 1;
3749 break;
3750 }
3751#endif /* CONFIG_FILS */
3752
Hai Shalomfdcde762020-04-02 11:19:20 -07003753#ifdef CONFIG_OWE
3754 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE && pmk_len > 32 &&
3755 owe_ptk_workaround == 1) {
3756 wpa_printf(MSG_DEBUG,
3757 "OWE: Try PTK derivation workaround with SHA256");
3758 owe_ptk_workaround = 2;
3759 continue;
3760 }
3761#endif /* CONFIG_OWE */
3762
Sunil Ravi7f769292024-07-23 22:21:32 +00003763 /* Some deployed STAs that advertise SecureLTF support in the
3764 * RSNXE in (Re)Association Request frames, do not derive KDK
3765 * during PTK generation. Try to work around this by checking if
3766 * a PTK derived without KDK would result in a matching MIC. */
3767 if (!sm->wpa_auth->conf.force_kdk_derivation &&
3768 derive_kdk && !no_kdk) {
3769 wpa_printf(MSG_DEBUG,
3770 "Try new PTK derivation without KDK as a workaround");
3771 no_kdk = true;
3772 goto try_without_kdk;
3773 }
3774
Roshan Pius3a1667e2018-07-03 15:17:14 -07003775 if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
3776 wpa_key_mgmt_sae(sm->wpa_key_mgmt))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003777 break;
3778 }
3779
Sunil Ravi7f769292024-07-23 22:21:32 +00003780 if (no_kdk && ok) {
3781 /* The workaround worked, so allow the 4-way handshake to be
3782 * completed with the PTK that was derived without the KDK. */
3783 wpa_printf(MSG_DEBUG,
3784 "PTK without KDK worked - misbehaving STA "
3785 MACSTR, MAC2STR(sm->addr));
3786 }
3787
Sunil Ravia04bd252022-05-02 22:54:18 -07003788 if (!ok && wpa_key_mgmt_wpa_psk_no_sae(sm->wpa_key_mgmt) &&
3789 wpa_auth->conf.radius_psk && wpa_auth->cb->request_radius_psk &&
3790 !sm->waiting_radius_psk) {
3791 wpa_printf(MSG_DEBUG, "No PSK available - ask RADIUS server");
3792 wpa_auth->cb->request_radius_psk(wpa_auth->cb_ctx, sm->addr,
3793 sm->wpa_key_mgmt,
3794 sm->ANonce,
3795 sm->last_rx_eapol_key,
3796 sm->last_rx_eapol_key_len);
3797 sm->waiting_radius_psk = 1;
Sunil Raviaf8751c2023-03-29 11:35:17 -07003798 goto out;
Sunil Ravia04bd252022-05-02 22:54:18 -07003799 }
3800
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003801 if (!ok) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07003802 wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm),
3803 LOGGER_DEBUG,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003804 "invalid MIC in msg 2/4 of 4-Way Handshake");
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07003805 if (psk_found)
3806 wpa_auth_psk_failure_report(sm->wpa_auth, sm->addr);
Sunil Raviaf8751c2023-03-29 11:35:17 -07003807 goto out;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003808 }
3809
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003810 /*
3811 * Note: last_rx_eapol_key length fields have already been validated in
3812 * wpa_receive().
3813 */
3814 hdr = (struct ieee802_1x_hdr *) sm->last_rx_eapol_key;
3815 key = (struct wpa_eapol_key *) (hdr + 1);
3816 mic = (u8 *) (key + 1);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003817 key_info = WPA_GET_BE16(key->key_info);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003818 key_data = mic + mic_len + 2;
3819 key_data_length = WPA_GET_BE16(mic + mic_len);
3820 if (key_data_length > sm->last_rx_eapol_key_len - sizeof(*hdr) -
3821 sizeof(*key) - mic_len - 2)
Sunil Raviaf8751c2023-03-29 11:35:17 -07003822 goto out;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003823
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003824 ver = key_info & WPA_KEY_INFO_TYPE_MASK;
3825 if (mic_len && (key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
3826 if (ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES &&
3827 ver != WPA_KEY_INFO_TYPE_AES_128_CMAC &&
3828 !wpa_use_aes_key_wrap(sm->wpa_key_mgmt)) {
3829 wpa_printf(MSG_INFO,
3830 "Unsupported EAPOL-Key Key Data field encryption");
3831 goto out;
3832 }
3833
3834 if (key_data_length < 8 || key_data_length % 8) {
3835 wpa_printf(MSG_INFO,
3836 "RSN: Unsupported AES-WRAP len %u",
3837 key_data_length);
3838 goto out;
3839 }
3840 key_data_length -= 8; /* AES-WRAP adds 8 bytes */
3841 key_data_buf = os_malloc(key_data_length);
3842 if (!key_data_buf)
3843 goto out;
3844 key_data_buf_len = key_data_length;
3845 if (aes_unwrap(PTK.kek, PTK.kek_len, key_data_length / 8,
3846 key_data, key_data_buf)) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003847 wpa_printf(MSG_INFO,
3848 "RSN: AES unwrap failed - could not decrypt EAPOL-Key key data");
3849 goto out;
3850 }
3851 key_data = key_data_buf;
3852 wpa_hexdump_key(MSG_DEBUG, "RSN: Decrypted EAPOL-Key Key Data",
3853 key_data, key_data_length);
3854 }
3855
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003856 if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07003857 wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003858 "received EAPOL-Key msg 2/4 with invalid Key Data contents");
Sunil Raviaf8751c2023-03-29 11:35:17 -07003859 goto out;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003860 }
3861 if (kde.rsn_ie) {
3862 eapol_key_ie = kde.rsn_ie;
3863 eapol_key_ie_len = kde.rsn_ie_len;
3864 } else if (kde.osen) {
3865 eapol_key_ie = kde.osen;
3866 eapol_key_ie_len = kde.osen_len;
3867 } else {
3868 eapol_key_ie = kde.wpa_ie;
3869 eapol_key_ie_len = kde.wpa_ie_len;
3870 }
3871 ft = sm->wpa == WPA_VERSION_WPA2 && wpa_key_mgmt_ft(sm->wpa_key_mgmt);
Hai Shalomfdcde762020-04-02 11:19:20 -07003872 if (!sm->wpa_ie ||
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003873 wpa_compare_rsn_ie(ft, sm->wpa_ie, sm->wpa_ie_len,
3874 eapol_key_ie, eapol_key_ie_len)) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07003875 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003876 "WPA IE from (Re)AssocReq did not match with msg 2/4");
3877 if (sm->wpa_ie) {
3878 wpa_hexdump(MSG_DEBUG, "WPA IE in AssocReq",
3879 sm->wpa_ie, sm->wpa_ie_len);
3880 }
3881 wpa_hexdump(MSG_DEBUG, "WPA IE in msg 2/4",
3882 eapol_key_ie, eapol_key_ie_len);
3883 /* MLME-DEAUTHENTICATE.request */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003884 wpa_sta_disconnect(wpa_auth, sm->addr,
3885 WLAN_REASON_PREV_AUTH_NOT_VALID);
Sunil Raviaf8751c2023-03-29 11:35:17 -07003886 goto out;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003887 }
Hai Shalomc3565922019-10-28 11:58:20 -07003888 if ((!sm->rsnxe && kde.rsnxe) ||
3889 (sm->rsnxe && !kde.rsnxe) ||
3890 (sm->rsnxe && kde.rsnxe &&
3891 (sm->rsnxe_len != kde.rsnxe_len ||
3892 os_memcmp(sm->rsnxe, kde.rsnxe, sm->rsnxe_len) != 0))) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07003893 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
Hai Shalomc3565922019-10-28 11:58:20 -07003894 "RSNXE from (Re)AssocReq did not match the one in EAPOL-Key msg 2/4");
3895 wpa_hexdump(MSG_DEBUG, "RSNXE in AssocReq",
3896 sm->rsnxe, sm->rsnxe_len);
3897 wpa_hexdump(MSG_DEBUG, "RSNXE in EAPOL-Key msg 2/4",
3898 kde.rsnxe, kde.rsnxe_len);
3899 /* MLME-DEAUTHENTICATE.request */
3900 wpa_sta_disconnect(wpa_auth, sm->addr,
3901 WLAN_REASON_PREV_AUTH_NOT_VALID);
Sunil Raviaf8751c2023-03-29 11:35:17 -07003902 goto out;
Hai Shalomc3565922019-10-28 11:58:20 -07003903 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003904#ifdef CONFIG_OCV
3905 if (wpa_auth_uses_ocv(sm)) {
3906 struct wpa_channel_info ci;
3907 int tx_chanwidth;
3908 int tx_seg1_idx;
Hai Shalom899fcc72020-10-19 14:38:18 -07003909 enum oci_verify_result res;
Hai Shalom74f70d42019-02-11 14:42:39 -08003910
3911 if (wpa_channel_info(wpa_auth, &ci) != 0) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07003912 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
3913 LOGGER_INFO,
Hai Shalom74f70d42019-02-11 14:42:39 -08003914 "Failed to get channel info to validate received OCI in EAPOL-Key 2/4");
Sunil Raviaf8751c2023-03-29 11:35:17 -07003915 goto out;
Hai Shalom74f70d42019-02-11 14:42:39 -08003916 }
3917
3918 if (get_sta_tx_parameters(sm,
3919 channel_width_to_int(ci.chanwidth),
3920 ci.seg1_idx, &tx_chanwidth,
3921 &tx_seg1_idx) < 0)
Sunil Raviaf8751c2023-03-29 11:35:17 -07003922 goto out;
Hai Shalom74f70d42019-02-11 14:42:39 -08003923
Hai Shalom899fcc72020-10-19 14:38:18 -07003924 res = ocv_verify_tx_params(kde.oci, kde.oci_len, &ci,
3925 tx_chanwidth, tx_seg1_idx);
3926 if (wpa_auth_uses_ocv(sm) == 2 && res == OCI_NOT_FOUND) {
3927 /* Work around misbehaving STAs */
Sunil Raviaf8751c2023-03-29 11:35:17 -07003928 wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
3929 LOGGER_INFO,
Hai Shalom899fcc72020-10-19 14:38:18 -07003930 "Disable OCV with a STA that does not send OCI");
3931 wpa_auth_set_ocv(sm, 0);
3932 } else if (res != OCI_SUCCESS) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07003933 wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
3934 LOGGER_INFO,
Hai Shalom899fcc72020-10-19 14:38:18 -07003935 "OCV failed: %s", ocv_errorstr);
3936 if (wpa_auth->conf.msg_ctx)
3937 wpa_msg(wpa_auth->conf.msg_ctx, MSG_INFO,
3938 OCV_FAILURE "addr=" MACSTR
3939 " frame=eapol-key-m2 error=%s",
Sunil Raviaf8751c2023-03-29 11:35:17 -07003940 MAC2STR(wpa_auth_get_spa(sm)),
3941 ocv_errorstr);
3942 goto out;
Hai Shalom74f70d42019-02-11 14:42:39 -08003943 }
3944 }
3945#endif /* CONFIG_OCV */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003946#ifdef CONFIG_IEEE80211R_AP
3947 if (ft && ft_check_msg_2_of_4(wpa_auth, sm, &kde) < 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003948 wpa_sta_disconnect(wpa_auth, sm->addr,
3949 WLAN_REASON_PREV_AUTH_NOT_VALID);
Sunil Raviaf8751c2023-03-29 11:35:17 -07003950 goto out;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003951 }
3952#endif /* CONFIG_IEEE80211R_AP */
Sunil Ravic0f5d412024-09-11 22:12:49 +00003953
3954 /* Verify RSN Selection element for RSN overriding */
3955 if ((wpa_auth->conf.rsn_override_key_mgmt ||
3956 wpa_auth->conf.rsn_override_key_mgmt_2) &&
3957 ((rsn_is_snonce_cookie(sm->SNonce) && !kde.rsn_selection) ||
3958 (!rsn_is_snonce_cookie(sm->SNonce) && kde.rsn_selection) ||
3959 (sm->rsn_selection && !kde.rsn_selection) ||
3960 (!sm->rsn_selection && kde.rsn_selection) ||
3961 (sm->rsn_selection && kde.rsn_selection &&
3962 (sm->rsn_selection_len != kde.rsn_selection_len ||
3963 os_memcmp(sm->rsn_selection, kde.rsn_selection,
3964 sm->rsn_selection_len) != 0)))) {
3965 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
3966 "RSN Selection element from (Re)AssocReq did not match the one in EAPOL-Key msg 2/4");
3967 wpa_printf(MSG_DEBUG,
3968 "SNonce cookie for RSN overriding %sused",
3969 rsn_is_snonce_cookie(sm->SNonce) ? "" : "not ");
3970 wpa_hexdump(MSG_DEBUG, "RSN Selection in AssocReq",
3971 sm->rsn_selection, sm->rsn_selection_len);
3972 wpa_hexdump(MSG_DEBUG, "RSN Selection in EAPOL-Key msg 2/4",
3973 kde.rsn_selection, kde.rsn_selection_len);
3974 /* MLME-DEAUTHENTICATE.request */
3975 wpa_sta_disconnect(wpa_auth, sm->addr,
3976 WLAN_REASON_PREV_AUTH_NOT_VALID);
3977 goto out;
3978
3979 }
3980
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003981#ifdef CONFIG_P2P
3982 if (kde.ip_addr_req && kde.ip_addr_req[0] &&
3983 wpa_auth->ip_pool && WPA_GET_BE32(sm->ip_addr) == 0) {
3984 int idx;
3985 wpa_printf(MSG_DEBUG,
3986 "P2P: IP address requested in EAPOL-Key exchange");
3987 idx = bitfield_get_first_zero(wpa_auth->ip_pool);
3988 if (idx >= 0) {
3989 u32 start = WPA_GET_BE32(wpa_auth->conf.ip_addr_start);
3990 bitfield_set(wpa_auth->ip_pool, idx);
Sunil8cd6f4d2022-06-28 18:40:46 +00003991 sm->ip_addr_bit = idx;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003992 WPA_PUT_BE32(sm->ip_addr, start + idx);
3993 wpa_printf(MSG_DEBUG,
3994 "P2P: Assigned IP address %u.%u.%u.%u to "
Sunil8cd6f4d2022-06-28 18:40:46 +00003995 MACSTR " (bit %u)",
3996 sm->ip_addr[0], sm->ip_addr[1],
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003997 sm->ip_addr[2], sm->ip_addr[3],
Sunil Raviaf8751c2023-03-29 11:35:17 -07003998 MAC2STR(wpa_auth_get_spa(sm)),
3999 sm->ip_addr_bit);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004000 }
4001 }
4002#endif /* CONFIG_P2P */
4003
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004004#ifdef CONFIG_DPP2
4005 if (DPP_VERSION > 1 && kde.dpp_kde) {
4006 wpa_printf(MSG_DEBUG,
4007 "DPP: peer Protocol Version %u Flags 0x%x",
4008 kde.dpp_kde[0], kde.dpp_kde[1]);
4009 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP &&
4010 wpa_auth->conf.dpp_pfs != 2 &&
4011 (kde.dpp_kde[1] & DPP_KDE_PFS_ALLOWED) &&
4012 !sm->dpp_z) {
4013 wpa_printf(MSG_INFO,
4014 "DPP: Peer indicated it supports PFS and local configuration allows this, but PFS was not negotiated for the association");
4015 wpa_sta_disconnect(wpa_auth, sm->addr,
4016 WLAN_REASON_PREV_AUTH_NOT_VALID);
Sunil Raviaf8751c2023-03-29 11:35:17 -07004017 goto out;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004018 }
4019 }
4020#endif /* CONFIG_DPP2 */
4021
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004022 if (wpa_auth_validate_ml_kdes_m2(sm, &kde) < 0) {
4023 wpa_sta_disconnect(wpa_auth, sm->addr,
4024 WLAN_REASON_PREV_AUTH_NOT_VALID);
4025 return;
4026 }
4027
Hai Shalom021b0b52019-04-10 11:17:58 -07004028 if (vlan_id && wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
4029 wpa_auth_update_vlan(wpa_auth, sm->addr, vlan_id) < 0) {
4030 wpa_sta_disconnect(wpa_auth, sm->addr,
4031 WLAN_REASON_PREV_AUTH_NOT_VALID);
Sunil Raviaf8751c2023-03-29 11:35:17 -07004032 goto out;
Hai Shalom021b0b52019-04-10 11:17:58 -07004033 }
4034
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004035 sm->pending_1_of_4_timeout = 0;
4036 eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm);
4037
Hai Shalom60840252021-02-19 19:02:11 -08004038 if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) && sm->PMK != pmk) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004039 /* PSK may have changed from the previous choice, so update
4040 * state machine data based on whatever PSK was selected here.
4041 */
4042 os_memcpy(sm->PMK, pmk, PMK_LEN);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004043 sm->pmk_len = PMK_LEN;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004044 }
4045
Hai Shalome21d4e82020-04-29 16:34:06 -07004046 sm->MICVerified = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004047
Sunil Raviaf8751c2023-03-29 11:35:17 -07004048#ifdef CONFIG_IEEE80211R_AP
4049 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt) && !sm->ft_completed) {
4050 wpa_printf(MSG_DEBUG, "FT: Store PMK-R0/PMK-R1");
4051 wpa_auth_ft_store_keys(sm, pmk_r0, pmk_r1, pmk_r0_name,
4052 key_len);
4053 }
4054#endif /* CONFIG_IEEE80211R_AP */
4055
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004056 os_memcpy(&sm->PTK, &PTK, sizeof(PTK));
Hai Shalom81f62d82019-07-22 12:10:00 -07004057 forced_memzero(&PTK, sizeof(PTK));
Hai Shalome21d4e82020-04-29 16:34:06 -07004058 sm->PTK_valid = true;
Sunil Raviaf8751c2023-03-29 11:35:17 -07004059out:
4060 forced_memzero(pmk_r0, sizeof(pmk_r0));
4061 forced_memzero(pmk_r1, sizeof(pmk_r1));
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004062 bin_clear_free(key_data_buf, key_data_buf_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004063}
4064
4065
4066SM_STATE(WPA_PTK, PTKCALCNEGOTIATING2)
4067{
4068 SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING2, wpa_ptk);
4069 sm->TimeoutCtr = 0;
4070}
4071
4072
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004073static int ieee80211w_kde_len(struct wpa_state_machine *sm)
4074{
Hai Shalomfdcde762020-04-02 11:19:20 -07004075 size_t len = 0;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004076 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
Hai Shalomfdcde762020-04-02 11:19:20 -07004077
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004078 if (sm->mgmt_frame_prot) {
Hai Shalomfdcde762020-04-02 11:19:20 -07004079 len += 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004080 len += wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher);
Hai Shalomfdcde762020-04-02 11:19:20 -07004081 }
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004082
4083 if (wpa_auth->conf.tx_bss_auth)
4084 wpa_auth = wpa_auth->conf.tx_bss_auth;
Hai Shalomfdcde762020-04-02 11:19:20 -07004085 if (sm->mgmt_frame_prot && sm->wpa_auth->conf.beacon_prot) {
4086 len += 2 + RSN_SELECTOR_LEN + WPA_BIGTK_KDE_PREFIX_LEN;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004087 len += wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004088 }
4089
Hai Shalomfdcde762020-04-02 11:19:20 -07004090 return len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004091}
4092
4093
4094static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos)
4095{
4096 struct wpa_igtk_kde igtk;
Hai Shalomfdcde762020-04-02 11:19:20 -07004097 struct wpa_bigtk_kde bigtk;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004098 struct wpa_group *gsm = sm->group;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004099 u8 rsc[WPA_KEY_RSC_LEN];
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004100 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
4101 struct wpa_auth_config *conf = &wpa_auth->conf;
Hai Shalomfdcde762020-04-02 11:19:20 -07004102 size_t len = wpa_cipher_key_len(conf->group_mgmt_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004103
4104 if (!sm->mgmt_frame_prot)
4105 return pos;
4106
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004107#ifdef CONFIG_IEEE80211BE
4108 if (sm->mld_assoc_link_id >= 0)
4109 return pos; /* Use per-link MLO KDEs instead */
4110#endif /* CONFIG_IEEE80211BE */
4111
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004112 igtk.keyid[0] = gsm->GN_igtk;
4113 igtk.keyid[1] = 0;
4114 if (gsm->wpa_group_state != WPA_GROUP_SETKEYSDONE ||
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004115 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, rsc) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004116 os_memset(igtk.pn, 0, sizeof(igtk.pn));
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004117 else
4118 os_memcpy(igtk.pn, rsc, sizeof(igtk.pn));
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004119 os_memcpy(igtk.igtk, gsm->IGTK[gsm->GN_igtk - 4], len);
Hai Shalomfdcde762020-04-02 11:19:20 -07004120 if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004121 /*
4122 * Provide unique random IGTK to each STA to prevent use of
4123 * IGTK in the BSS.
4124 */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004125 if (random_get_bytes(igtk.igtk, len) < 0)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004126 return pos;
4127 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004128 pos = wpa_add_kde(pos, RSN_KEY_DATA_IGTK,
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004129 (const u8 *) &igtk, WPA_IGTK_KDE_PREFIX_LEN + len,
4130 NULL, 0);
Sunil Ravia04bd252022-05-02 22:54:18 -07004131 forced_memzero(&igtk, sizeof(igtk));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004132
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004133 if (wpa_auth->conf.tx_bss_auth) {
4134 wpa_auth = wpa_auth->conf.tx_bss_auth;
4135 conf = &wpa_auth->conf;
4136 len = wpa_cipher_key_len(conf->group_mgmt_cipher);
4137 gsm = wpa_auth->group;
4138 }
4139
4140 if (!sm->wpa_auth->conf.beacon_prot)
Hai Shalomfdcde762020-04-02 11:19:20 -07004141 return pos;
4142
4143 bigtk.keyid[0] = gsm->GN_bigtk;
4144 bigtk.keyid[1] = 0;
4145 if (gsm->wpa_group_state != WPA_GROUP_SETKEYSDONE ||
4146 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_bigtk, rsc) < 0)
4147 os_memset(bigtk.pn, 0, sizeof(bigtk.pn));
4148 else
4149 os_memcpy(bigtk.pn, rsc, sizeof(bigtk.pn));
4150 os_memcpy(bigtk.bigtk, gsm->BIGTK[gsm->GN_bigtk - 6], len);
Hai Shalom899fcc72020-10-19 14:38:18 -07004151 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
4152 /*
4153 * Provide unique random BIGTK to each OSEN STA to prevent use
4154 * of BIGTK in the BSS.
4155 */
4156 if (random_get_bytes(bigtk.bigtk, len) < 0)
4157 return pos;
4158 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004159 pos = wpa_add_kde(pos, RSN_KEY_DATA_BIGTK,
4160 (const u8 *) &bigtk, WPA_BIGTK_KDE_PREFIX_LEN + len,
4161 NULL, 0);
Sunil Ravia04bd252022-05-02 22:54:18 -07004162 forced_memzero(&bigtk, sizeof(bigtk));
Hai Shalomfdcde762020-04-02 11:19:20 -07004163
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004164 return pos;
4165}
4166
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004167
Hai Shalom74f70d42019-02-11 14:42:39 -08004168static int ocv_oci_len(struct wpa_state_machine *sm)
4169{
4170#ifdef CONFIG_OCV
4171 if (wpa_auth_uses_ocv(sm))
4172 return OCV_OCI_KDE_LEN;
4173#endif /* CONFIG_OCV */
4174 return 0;
4175}
4176
Hai Shalom899fcc72020-10-19 14:38:18 -07004177
4178static int ocv_oci_add(struct wpa_state_machine *sm, u8 **argpos,
4179 unsigned int freq)
Hai Shalom74f70d42019-02-11 14:42:39 -08004180{
4181#ifdef CONFIG_OCV
4182 struct wpa_channel_info ci;
4183
4184 if (!wpa_auth_uses_ocv(sm))
4185 return 0;
4186
4187 if (wpa_channel_info(sm->wpa_auth, &ci) != 0) {
4188 wpa_printf(MSG_WARNING,
4189 "Failed to get channel info for OCI element");
4190 return -1;
4191 }
Hai Shalom899fcc72020-10-19 14:38:18 -07004192#ifdef CONFIG_TESTING_OPTIONS
4193 if (freq) {
4194 wpa_printf(MSG_INFO,
4195 "TEST: Override OCI KDE frequency %d -> %u MHz",
4196 ci.frequency, freq);
4197 ci.frequency = freq;
4198 }
4199#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom74f70d42019-02-11 14:42:39 -08004200
4201 return ocv_insert_oci_kde(&ci, argpos);
4202#else /* CONFIG_OCV */
4203 return 0;
4204#endif /* CONFIG_OCV */
4205}
4206
4207
Hai Shalomfdcde762020-04-02 11:19:20 -07004208#ifdef CONFIG_TESTING_OPTIONS
4209static u8 * replace_ie(const char *name, const u8 *old_buf, size_t *len, u8 eid,
4210 const u8 *ie, size_t ie_len)
4211{
4212 const u8 *elem;
4213 u8 *buf;
4214
4215 wpa_printf(MSG_DEBUG, "TESTING: %s EAPOL override", name);
4216 wpa_hexdump(MSG_DEBUG, "TESTING: wpa_ie before override",
4217 old_buf, *len);
4218 buf = os_malloc(*len + ie_len);
4219 if (!buf)
4220 return NULL;
4221 os_memcpy(buf, old_buf, *len);
4222 elem = get_ie(buf, *len, eid);
4223 if (elem) {
4224 u8 elem_len = 2 + elem[1];
4225
4226 os_memmove((void *) elem, elem + elem_len,
4227 *len - (elem - buf) - elem_len);
4228 *len -= elem_len;
4229 }
4230 os_memcpy(buf + *len, ie, ie_len);
4231 *len += ie_len;
4232 wpa_hexdump(MSG_DEBUG, "TESTING: wpa_ie after EAPOL override",
4233 buf, *len);
4234
4235 return buf;
4236}
4237#endif /* CONFIG_TESTING_OPTIONS */
4238
4239
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004240#ifdef CONFIG_IEEE80211BE
4241
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004242void wpa_auth_ml_get_key_info(struct wpa_authenticator *a,
4243 struct wpa_auth_ml_link_key_info *info,
Sunil Ravic0f5d412024-09-11 22:12:49 +00004244 bool mgmt_frame_prot, bool beacon_prot,
4245 bool rekey)
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004246{
4247 struct wpa_group *gsm = a->group;
4248 u8 rsc[WPA_KEY_RSC_LEN];
4249
4250 wpa_printf(MSG_DEBUG,
4251 "MLD: Get group key info: link_id=%u, IGTK=%u, BIGTK=%u",
4252 info->link_id, mgmt_frame_prot, beacon_prot);
4253
4254 info->gtkidx = gsm->GN & 0x03;
4255 info->gtk = gsm->GTK[gsm->GN - 1];
4256 info->gtk_len = gsm->GTK_len;
4257
Sunil Ravic0f5d412024-09-11 22:12:49 +00004258 if (rekey || wpa_auth_get_seqnum(a, NULL, gsm->GN, rsc) < 0)
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004259 os_memset(info->pn, 0, sizeof(info->pn));
4260 else
4261 os_memcpy(info->pn, rsc, sizeof(info->pn));
4262
4263 if (!mgmt_frame_prot)
4264 return;
4265
4266 info->igtkidx = gsm->GN_igtk;
4267 info->igtk = gsm->IGTK[gsm->GN_igtk - 4];
4268 info->igtk_len = wpa_cipher_key_len(a->conf.group_mgmt_cipher);
4269
Sunil Ravic0f5d412024-09-11 22:12:49 +00004270 if (rekey || wpa_auth_get_seqnum(a, NULL, gsm->GN_igtk, rsc) < 0)
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004271 os_memset(info->ipn, 0, sizeof(info->ipn));
4272 else
4273 os_memcpy(info->ipn, rsc, sizeof(info->ipn));
4274
4275 if (!beacon_prot)
4276 return;
4277
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004278 if (a->conf.tx_bss_auth) {
4279 a = a->conf.tx_bss_auth;
4280 gsm = a->group;
4281 }
4282
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004283 info->bigtkidx = gsm->GN_bigtk;
4284 info->bigtk = gsm->BIGTK[gsm->GN_bigtk - 6];
4285
Sunil Ravic0f5d412024-09-11 22:12:49 +00004286 if (rekey || wpa_auth_get_seqnum(a, NULL, gsm->GN_bigtk, rsc) < 0)
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004287 os_memset(info->bipn, 0, sizeof(info->bipn));
4288 else
4289 os_memcpy(info->bipn, rsc, sizeof(info->bipn));
4290}
4291
4292
4293static void wpa_auth_get_ml_key_info(struct wpa_authenticator *wpa_auth,
Sunil Ravic0f5d412024-09-11 22:12:49 +00004294 struct wpa_auth_ml_key_info *info,
4295 bool rekey)
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004296{
4297 if (!wpa_auth->cb->get_ml_key_info)
4298 return;
4299
Sunil Ravic0f5d412024-09-11 22:12:49 +00004300 wpa_auth->cb->get_ml_key_info(wpa_auth->cb_ctx, info, rekey);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004301}
4302
4303
4304static size_t wpa_auth_ml_group_kdes_len(struct wpa_state_machine *sm)
4305{
Sunil Ravi7f769292024-07-23 22:21:32 +00004306 struct wpa_authenticator *wpa_auth;
4307 size_t kde_len = 0;
4308 int link_id;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004309
4310 if (sm->mld_assoc_link_id < 0)
4311 return 0;
4312
Sunil Ravi7f769292024-07-23 22:21:32 +00004313 for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
4314 if (!sm->mld_links[link_id].valid)
4315 continue;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004316
Sunil Ravi7f769292024-07-23 22:21:32 +00004317 wpa_auth = sm->mld_links[link_id].wpa_auth;
4318 if (!wpa_auth || !wpa_auth->group)
4319 continue;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004320
Sunil Ravi7f769292024-07-23 22:21:32 +00004321 /* MLO GTK KDE
4322 * Header + Key ID + Tx + LinkID + PN + GTK */
4323 kde_len += KDE_HDR_LEN + 1 + RSN_PN_LEN;
4324 kde_len += wpa_auth->group->GTK_len;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004325
Sunil Ravi7f769292024-07-23 22:21:32 +00004326 if (!sm->mgmt_frame_prot)
4327 continue;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004328
Sunil Ravi7f769292024-07-23 22:21:32 +00004329 if (wpa_auth->conf.tx_bss_auth)
4330 wpa_auth = wpa_auth->conf.tx_bss_auth;
4331
4332 /* MLO IGTK KDE
4333 * Header + Key ID + IPN + LinkID + IGTK */
4334 kde_len += KDE_HDR_LEN + WPA_IGTK_KDE_PREFIX_LEN + 1;
4335 kde_len += wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher);
4336
4337 if (!wpa_auth->conf.beacon_prot)
4338 continue;
4339
4340 /* MLO BIGTK KDE
4341 * Header + Key ID + BIPN + LinkID + BIGTK */
4342 kde_len += KDE_HDR_LEN + WPA_BIGTK_KDE_PREFIX_LEN + 1;
4343 kde_len += wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004344 }
4345
Sunil Ravi7f769292024-07-23 22:21:32 +00004346 wpa_printf(MSG_DEBUG, "MLO Group KDEs len = %zu", kde_len);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004347
4348 return kde_len;
4349}
4350
4351
4352static u8 * wpa_auth_ml_group_kdes(struct wpa_state_machine *sm, u8 *pos)
4353{
4354 struct wpa_auth_ml_key_info ml_key_info;
4355 unsigned int i, link_id;
Sunil Ravi7f769292024-07-23 22:21:32 +00004356 u8 *start = pos;
Sunil Ravic0f5d412024-09-11 22:12:49 +00004357 bool rekey = sm->wpa_ptk_group_state == WPA_PTK_GROUP_REKEYNEGOTIATING;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004358
4359 /* First fetch the key information from all the authenticators */
4360 os_memset(&ml_key_info, 0, sizeof(ml_key_info));
4361 ml_key_info.n_mld_links = sm->n_mld_affiliated_links + 1;
4362
4363 /*
4364 * Assume that management frame protection and beacon protection are the
4365 * same on all links.
4366 */
4367 ml_key_info.mgmt_frame_prot = sm->mgmt_frame_prot;
4368 ml_key_info.beacon_prot = sm->wpa_auth->conf.beacon_prot;
4369
4370 for (i = 0, link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
4371 if (!sm->mld_links[link_id].valid)
4372 continue;
4373
4374 ml_key_info.links[i++].link_id = link_id;
4375 }
4376
Sunil Ravic0f5d412024-09-11 22:12:49 +00004377 wpa_auth_get_ml_key_info(sm->wpa_auth, &ml_key_info, rekey);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004378
4379 /* Add MLO GTK KDEs */
4380 for (i = 0, link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004381 if (!sm->mld_links[link_id].valid ||
4382 !ml_key_info.links[i].gtk_len)
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004383 continue;
4384
4385 wpa_printf(MSG_DEBUG, "RSN: MLO GTK: link=%u", link_id);
4386 wpa_hexdump_key(MSG_DEBUG, "RSN: MLO GTK",
4387 ml_key_info.links[i].gtk,
4388 ml_key_info.links[i].gtk_len);
4389
4390 *pos++ = WLAN_EID_VENDOR_SPECIFIC;
4391 *pos++ = RSN_SELECTOR_LEN + 1 + 6 +
4392 ml_key_info.links[i].gtk_len;
4393
4394 RSN_SELECTOR_PUT(pos, RSN_KEY_DATA_MLO_GTK);
4395 pos += RSN_SELECTOR_LEN;
4396
4397 *pos++ = (ml_key_info.links[i].gtkidx & 0x3) | (link_id << 4);
4398
4399 os_memcpy(pos, ml_key_info.links[i].pn, 6);
4400 pos += 6;
4401
4402 os_memcpy(pos, ml_key_info.links[i].gtk,
4403 ml_key_info.links[i].gtk_len);
4404 pos += ml_key_info.links[i].gtk_len;
4405
4406 i++;
4407 }
4408
Sunil Ravi7f769292024-07-23 22:21:32 +00004409 if (!sm->mgmt_frame_prot) {
4410 wpa_printf(MSG_DEBUG, "RSN: MLO Group KDE len = %ld",
4411 pos - start);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004412 return pos;
Sunil Ravi7f769292024-07-23 22:21:32 +00004413 }
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004414
4415 /* Add MLO IGTK KDEs */
4416 for (i = 0, link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004417 if (!sm->mld_links[link_id].valid ||
4418 !ml_key_info.links[i].igtk_len)
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004419 continue;
4420
4421 wpa_printf(MSG_DEBUG, "RSN: MLO IGTK: link=%u", link_id);
4422 wpa_hexdump_key(MSG_DEBUG, "RSN: MLO IGTK",
4423 ml_key_info.links[i].igtk,
4424 ml_key_info.links[i].igtk_len);
4425
4426 *pos++ = WLAN_EID_VENDOR_SPECIFIC;
4427 *pos++ = RSN_SELECTOR_LEN + 2 + 1 +
4428 sizeof(ml_key_info.links[i].ipn) +
4429 ml_key_info.links[i].igtk_len;
4430
4431 RSN_SELECTOR_PUT(pos, RSN_KEY_DATA_MLO_IGTK);
4432 pos += RSN_SELECTOR_LEN;
4433
4434 /* Add the Key ID */
4435 *pos++ = ml_key_info.links[i].igtkidx;
4436 *pos++ = 0;
4437
4438 /* Add the IPN */
4439 os_memcpy(pos, ml_key_info.links[i].ipn,
4440 sizeof(ml_key_info.links[i].ipn));
4441 pos += sizeof(ml_key_info.links[i].ipn);
4442
4443 *pos++ = ml_key_info.links[i].link_id << 4;
4444
4445 os_memcpy(pos, ml_key_info.links[i].igtk,
4446 ml_key_info.links[i].igtk_len);
4447 pos += ml_key_info.links[i].igtk_len;
4448
4449 i++;
4450 }
4451
Sunil Ravi7f769292024-07-23 22:21:32 +00004452 if (!sm->wpa_auth->conf.beacon_prot) {
4453 wpa_printf(MSG_DEBUG, "RSN: MLO Group KDE len = %ld",
4454 pos - start);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004455 return pos;
Sunil Ravi7f769292024-07-23 22:21:32 +00004456 }
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004457
4458 /* Add MLO BIGTK KDEs */
4459 for (i = 0, link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004460 if (!sm->mld_links[link_id].valid ||
4461 !ml_key_info.links[i].bigtk ||
4462 !ml_key_info.links[i].igtk_len)
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004463 continue;
4464
4465 wpa_printf(MSG_DEBUG, "RSN: MLO BIGTK: link=%u", link_id);
4466 wpa_hexdump_key(MSG_DEBUG, "RSN: MLO BIGTK",
4467 ml_key_info.links[i].bigtk,
4468 ml_key_info.links[i].igtk_len);
4469
4470 *pos++ = WLAN_EID_VENDOR_SPECIFIC;
4471 *pos++ = RSN_SELECTOR_LEN + 2 + 1 +
4472 sizeof(ml_key_info.links[i].bipn) +
4473 ml_key_info.links[i].igtk_len;
4474
4475 RSN_SELECTOR_PUT(pos, RSN_KEY_DATA_MLO_BIGTK);
4476 pos += RSN_SELECTOR_LEN;
4477
4478 /* Add the Key ID */
4479 *pos++ = ml_key_info.links[i].bigtkidx;
4480 *pos++ = 0;
4481
4482 /* Add the BIPN */
4483 os_memcpy(pos, ml_key_info.links[i].bipn,
4484 sizeof(ml_key_info.links[i].bipn));
4485 pos += sizeof(ml_key_info.links[i].bipn);
4486
4487 *pos++ = ml_key_info.links[i].link_id << 4;
4488
4489 os_memcpy(pos, ml_key_info.links[i].bigtk,
4490 ml_key_info.links[i].igtk_len);
4491 pos += ml_key_info.links[i].igtk_len;
4492
4493 i++;
4494 }
4495
Sunil Ravi7f769292024-07-23 22:21:32 +00004496 wpa_printf(MSG_DEBUG, "RSN: MLO Group KDE len = %ld", pos - start);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004497 return pos;
4498}
4499
4500#endif /* CONFIG_IEEE80211BE */
4501
4502
4503static size_t wpa_auth_ml_kdes_len(struct wpa_state_machine *sm)
4504{
4505 size_t kde_len = 0;
4506
4507#ifdef CONFIG_IEEE80211BE
4508 unsigned int link_id;
4509
4510 if (sm->mld_assoc_link_id < 0)
4511 return 0;
4512
4513 /* For the MAC Address KDE */
4514 kde_len = 2 + RSN_SELECTOR_LEN + ETH_ALEN;
4515
Sunil Ravic0f5d412024-09-11 22:12:49 +00004516 /* MLO Link KDE and RSN Override Link KDE for each link */
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004517 for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
Sunil Ravi7f769292024-07-23 22:21:32 +00004518 struct wpa_authenticator *wpa_auth;
Sunil Ravic0f5d412024-09-11 22:12:49 +00004519 const u8 *ie;
Sunil Ravi7f769292024-07-23 22:21:32 +00004520
4521 wpa_auth = wpa_get_link_auth(sm->wpa_auth, link_id);
4522 if (!wpa_auth)
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004523 continue;
4524
Sunil Ravic0f5d412024-09-11 22:12:49 +00004525 /* MLO Link KDE */
Sunil Ravi7f769292024-07-23 22:21:32 +00004526 kde_len += 2 + RSN_SELECTOR_LEN + 1 + ETH_ALEN;
Sunil Ravic0f5d412024-09-11 22:12:49 +00004527
Sunil Ravi7f769292024-07-23 22:21:32 +00004528 ie = get_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
4529 WLAN_EID_RSN);
Sunil Ravic0f5d412024-09-11 22:12:49 +00004530 if (ie)
Sunil Ravi7f769292024-07-23 22:21:32 +00004531 kde_len += 2 + ie[1];
4532
4533 ie = get_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
4534 WLAN_EID_RSNX);
Sunil Ravic0f5d412024-09-11 22:12:49 +00004535 if (ie)
4536 kde_len += 2 + ie[1];
4537
4538 if (!rsn_is_snonce_cookie(sm->SNonce))
4539 continue;
4540
4541 /* RSN Override Link KDE */
4542 kde_len += 2 + RSN_SELECTOR_LEN + 1;
4543
4544 ie = get_vendor_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
4545 RSNE_OVERRIDE_IE_VENDOR_TYPE);
4546 if (ie)
4547 kde_len += 2 + ie[1];
4548
4549 ie = get_vendor_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
4550 RSNE_OVERRIDE_2_IE_VENDOR_TYPE);
4551 if (ie)
4552 kde_len += 2 + ie[1];
4553
4554 ie = get_vendor_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
4555 RSNXE_OVERRIDE_IE_VENDOR_TYPE);
4556 if (ie)
Sunil Ravi7f769292024-07-23 22:21:32 +00004557 kde_len += 2 + ie[1];
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004558 }
4559
4560 kde_len += wpa_auth_ml_group_kdes_len(sm);
4561#endif /* CONFIG_IEEE80211BE */
4562
4563 return kde_len;
4564}
4565
4566
4567static u8 * wpa_auth_ml_kdes(struct wpa_state_machine *sm, u8 *pos)
4568{
4569#ifdef CONFIG_IEEE80211BE
4570 u8 link_id;
Sunil Ravi7f769292024-07-23 22:21:32 +00004571 u8 *start = pos;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004572
4573 if (sm->mld_assoc_link_id < 0)
4574 return pos;
4575
4576 wpa_printf(MSG_DEBUG, "RSN: MLD: Adding MAC Address KDE");
4577 pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR,
Sunil Ravi7f769292024-07-23 22:21:32 +00004578 sm->wpa_auth->mld_addr, ETH_ALEN, NULL, 0);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004579
4580 for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
Sunil Ravi7f769292024-07-23 22:21:32 +00004581 struct wpa_authenticator *wpa_auth;
Sunil Ravic0f5d412024-09-11 22:12:49 +00004582 const u8 *rsne, *rsnxe, *rsnoe, *rsno2e, *rsnxoe;
4583 size_t rsne_len, rsnxe_len, rsnoe_len, rsno2e_len, rsnxoe_len;
4584 size_t kde_len;
Sunil Ravi7f769292024-07-23 22:21:32 +00004585
4586 wpa_auth = wpa_get_link_auth(sm->wpa_auth, link_id);
4587 if (!wpa_auth)
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004588 continue;
4589
Sunil Ravi7f769292024-07-23 22:21:32 +00004590 rsne = get_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
4591 WLAN_EID_RSN);
4592 rsne_len = rsne ? 2 + rsne[1] : 0;
Sunil Ravi7f769292024-07-23 22:21:32 +00004593
4594 rsnxe = get_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
4595 WLAN_EID_RSNX);
4596 rsnxe_len = rsnxe ? 2 + rsnxe[1] : 0;
Sunil Ravi7f769292024-07-23 22:21:32 +00004597
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004598 wpa_printf(MSG_DEBUG,
4599 "RSN: MLO Link: link=%u, len=%zu", link_id,
4600 RSN_SELECTOR_LEN + 1 + ETH_ALEN +
Sunil Ravi7f769292024-07-23 22:21:32 +00004601 rsne_len + rsnxe_len);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004602
Sunil Ravic0f5d412024-09-11 22:12:49 +00004603 /* MLO Link KDE */
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004604 *pos++ = WLAN_EID_VENDOR_SPECIFIC;
4605 *pos++ = RSN_SELECTOR_LEN + 1 + ETH_ALEN +
Sunil Ravi7f769292024-07-23 22:21:32 +00004606 rsne_len + rsnxe_len;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004607
4608 RSN_SELECTOR_PUT(pos, RSN_KEY_DATA_MLO_LINK);
4609 pos += RSN_SELECTOR_LEN;
4610
4611 /* Add the Link Information */
4612 *pos = link_id;
Sunil Ravi7f769292024-07-23 22:21:32 +00004613 if (rsne_len)
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004614 *pos |= RSN_MLO_LINK_KDE_LI_RSNE_INFO;
Sunil Ravi7f769292024-07-23 22:21:32 +00004615 if (rsnxe_len)
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004616 *pos |= RSN_MLO_LINK_KDE_LI_RSNXE_INFO;
4617
4618 pos++;
Sunil Ravi7f769292024-07-23 22:21:32 +00004619 os_memcpy(pos, wpa_auth->addr, ETH_ALEN);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004620 pos += ETH_ALEN;
4621
Sunil Ravi7f769292024-07-23 22:21:32 +00004622 if (rsne_len) {
Sunil Ravic0f5d412024-09-11 22:12:49 +00004623 os_memcpy(pos, rsne, rsne_len);
4624 pos += rsne_len;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004625 }
4626
Sunil Ravi7f769292024-07-23 22:21:32 +00004627 if (rsnxe_len) {
Sunil Ravic0f5d412024-09-11 22:12:49 +00004628 os_memcpy(pos, rsnxe, rsnxe_len);
4629 pos += rsnxe_len;
4630 }
4631
4632 if (!rsn_is_snonce_cookie(sm->SNonce))
4633 continue;
4634
4635 rsnoe = get_vendor_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
4636 RSNE_OVERRIDE_IE_VENDOR_TYPE);
4637 rsnoe_len = rsnoe ? 2 + rsnoe[1] : 0;
4638
4639 rsno2e = get_vendor_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
4640 RSNE_OVERRIDE_2_IE_VENDOR_TYPE);
4641 rsno2e_len = rsno2e ? 2 + rsno2e[1] : 0;
4642
4643 rsnxoe = get_vendor_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
4644 RSNXE_OVERRIDE_IE_VENDOR_TYPE);
4645 rsnxoe_len = rsnxoe ? 2 + rsnxoe[1] : 0;
4646
4647 wpa_printf(MSG_DEBUG,
4648 "RSN: RSN Override Link KDE: link=%u, len=%zu",
4649 link_id, RSN_SELECTOR_LEN + rsnoe_len + rsno2e_len +
4650 rsnxoe_len);
4651
4652 /* RSN Override Link KDE */
4653 *pos++ = WLAN_EID_VENDOR_SPECIFIC;
4654 kde_len = RSN_SELECTOR_LEN + 1 + rsnoe_len + rsno2e_len +
4655 rsnxoe_len;
4656 if (kde_len > 255) {
4657 wpa_printf(MSG_ERROR,
4658 "RSN: RSNOE/RSNO2E/RSNXOE too long (KDE length %zu) to fit in RSN Override Link KDE for link %u",
4659 kde_len, link_id);
4660 return NULL;
4661 }
4662 *pos++ = kde_len;
4663
4664 RSN_SELECTOR_PUT(pos, WFA_KEY_DATA_RSN_OVERRIDE_LINK);
4665 pos += RSN_SELECTOR_LEN;
4666
4667 *pos++ = link_id;
4668
4669 if (rsnoe_len) {
4670 os_memcpy(pos, rsnoe, rsnoe_len);
4671 pos += rsnoe_len;
4672 }
4673
4674 if (rsno2e_len) {
4675 os_memcpy(pos, rsno2e, rsno2e_len);
4676 pos += rsno2e_len;
4677 }
4678
4679 if (rsnxoe_len) {
4680 os_memcpy(pos, rsnxoe, rsnxoe_len);
4681 pos += rsnxoe_len;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004682 }
4683 }
4684
Sunil Ravic0f5d412024-09-11 22:12:49 +00004685 wpa_printf(MSG_DEBUG,
4686 "RSN: MLO Link KDEs and RSN Override Link KDEs len = %ld",
4687 pos - start);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004688 pos = wpa_auth_ml_group_kdes(sm, pos);
4689#endif /* CONFIG_IEEE80211BE */
4690
4691 return pos;
4692}
4693
4694
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004695SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
4696{
Hai Shaloma20dcd72022-02-04 13:43:00 -08004697 u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde = NULL, *pos, stub_gtk[32];
Sunil Ravia04bd252022-05-02 22:54:18 -07004698 size_t gtk_len, kde_len = 0, wpa_ie_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004699 struct wpa_group *gsm = sm->group;
4700 u8 *wpa_ie;
Hai Shalomfdcde762020-04-02 11:19:20 -07004701 int secure, gtkidx, encr = 0;
Sunil Ravi7f769292024-07-23 22:21:32 +00004702 u8 *wpa_ie_buf = NULL, *wpa_ie_buf2 = NULL, *wpa_ie_buf3 = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -07004703 u8 hdr[2];
4704 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004705#ifdef CONFIG_IEEE80211BE
4706 bool is_mld = sm->mld_assoc_link_id >= 0;
4707#else /* CONFIG_IEEE80211BE */
4708 bool is_mld = false;
4709#endif /* CONFIG_IEEE80211BE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004710
4711 SM_ENTRY_MA(WPA_PTK, PTKINITNEGOTIATING, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07004712 sm->TimeoutEvt = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004713
4714 sm->TimeoutCtr++;
Hai Shalomfdcde762020-04-02 11:19:20 -07004715 if (conf->wpa_disable_eapol_key_retries && sm->TimeoutCtr > 1) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004716 /* Do not allow retransmission of EAPOL-Key msg 3/4 */
4717 return;
4718 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004719 if (sm->TimeoutCtr > conf->wpa_pairwise_update_count) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004720 /* No point in sending the EAPOL-Key - we will disconnect
4721 * immediately following this. */
4722 return;
4723 }
4724
4725 /* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, [MDIE],
Hai Shalomfdcde762020-04-02 11:19:20 -07004726 GTK[GN], IGTK, [BIGTK], [FTIE], [TIE * 2])
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004727 */
4728 os_memset(rsc, 0, WPA_KEY_RSC_LEN);
4729 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc);
4730 /* If FT is used, wpa_auth->wpa_ie includes both RSNIE and MDIE */
4731 wpa_ie = sm->wpa_auth->wpa_ie;
4732 wpa_ie_len = sm->wpa_auth->wpa_ie_len;
Hai Shalomfdcde762020-04-02 11:19:20 -07004733 if (sm->wpa == WPA_VERSION_WPA && (conf->wpa & WPA_PROTO_RSN) &&
4734 wpa_ie_len > wpa_ie[1] + 2U && wpa_ie[0] == WLAN_EID_RSN) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004735 /* WPA-only STA, remove RSN IE and possible MDIE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004736 wpa_ie = wpa_ie + wpa_ie[1] + 2;
Hai Shalom60840252021-02-19 19:02:11 -08004737 if (wpa_ie[0] == WLAN_EID_RSNX)
4738 wpa_ie = wpa_ie + wpa_ie[1] + 2;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004739 if (wpa_ie[0] == WLAN_EID_MOBILITY_DOMAIN)
4740 wpa_ie = wpa_ie + wpa_ie[1] + 2;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004741 wpa_ie_len = wpa_ie[1] + 2;
4742 }
Sunil Ravic0f5d412024-09-11 22:12:49 +00004743 if ((conf->rsn_override_key_mgmt || conf->rsn_override_key_mgmt_2) &&
4744 !rsn_is_snonce_cookie(sm->SNonce)) {
4745 u8 *ie;
4746 size_t ie_len;
4747 u32 ids[] = {
4748 RSNE_OVERRIDE_IE_VENDOR_TYPE,
4749 RSNE_OVERRIDE_2_IE_VENDOR_TYPE,
4750 RSNXE_OVERRIDE_IE_VENDOR_TYPE,
4751 0
4752 };
4753 int i;
Sunil Ravi7f769292024-07-23 22:21:32 +00004754
4755 wpa_printf(MSG_DEBUG,
Sunil Ravic0f5d412024-09-11 22:12:49 +00004756 "RSN: Remove RSNE/RSNXE override elements");
Sunil Ravi7f769292024-07-23 22:21:32 +00004757 wpa_hexdump(MSG_DEBUG, "EAPOL-Key msg 3/4 IEs before edits",
4758 wpa_ie, wpa_ie_len);
Sunil Ravic0f5d412024-09-11 22:12:49 +00004759 wpa_ie_buf3 = os_memdup(wpa_ie, wpa_ie_len);
Sunil Ravi7f769292024-07-23 22:21:32 +00004760 if (!wpa_ie_buf3)
4761 goto done;
Sunil Ravi7f769292024-07-23 22:21:32 +00004762 wpa_ie = wpa_ie_buf3;
Sunil Ravic0f5d412024-09-11 22:12:49 +00004763
4764 for (i = 0; ids[i]; i++) {
4765 ie = (u8 *) get_vendor_ie(wpa_ie, wpa_ie_len, ids[i]);
4766 if (ie) {
4767 ie_len = 2 + ie[1];
4768 os_memmove(ie, ie + ie_len,
4769 wpa_ie_len - (ie + ie_len - wpa_ie));
4770 wpa_ie_len -= ie_len;
4771 }
4772 }
Sunil Ravi7f769292024-07-23 22:21:32 +00004773 wpa_hexdump(MSG_DEBUG, "EAPOL-Key msg 3/4 IEs after edits",
4774 wpa_ie, wpa_ie_len);
4775 }
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004776#ifdef CONFIG_TESTING_OPTIONS
Hai Shalomfdcde762020-04-02 11:19:20 -07004777 if (conf->rsne_override_eapol_set) {
4778 wpa_ie_buf2 = replace_ie(
4779 "RSNE", wpa_ie, &wpa_ie_len, WLAN_EID_RSN,
4780 conf->rsne_override_eapol,
4781 conf->rsne_override_eapol_len);
4782 if (!wpa_ie_buf2)
4783 goto done;
4784 wpa_ie = wpa_ie_buf2;
4785 }
4786 if (conf->rsnxe_override_eapol_set) {
4787 wpa_ie_buf = replace_ie(
4788 "RSNXE", wpa_ie, &wpa_ie_len, WLAN_EID_RSNX,
4789 conf->rsnxe_override_eapol,
4790 conf->rsnxe_override_eapol_len);
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004791 if (!wpa_ie_buf)
Hai Shalomfdcde762020-04-02 11:19:20 -07004792 goto done;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004793 wpa_ie = wpa_ie_buf;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004794 }
4795#endif /* CONFIG_TESTING_OPTIONS */
Sunil Raviaf8751c2023-03-29 11:35:17 -07004796 wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004797 "sending 3/4 msg of 4-Way Handshake");
4798 if (sm->wpa == WPA_VERSION_WPA2) {
Hai Shalomfdcde762020-04-02 11:19:20 -07004799 if (sm->use_ext_key_id && sm->TimeoutCtr == 1 &&
4800 wpa_auth_set_key(sm->wpa_auth, 0,
4801 wpa_cipher_to_alg(sm->pairwise),
4802 sm->addr,
4803 sm->keyidx_active, sm->PTK.tk,
4804 wpa_cipher_key_len(sm->pairwise),
4805 KEY_FLAG_PAIRWISE_RX)) {
4806 wpa_sta_disconnect(sm->wpa_auth, sm->addr,
4807 WLAN_REASON_PREV_AUTH_NOT_VALID);
4808 return;
4809 }
4810
Sunil Ravi89eba102022-09-13 21:04:37 -07004811#ifdef CONFIG_PASN
4812 if (sm->wpa_auth->conf.secure_ltf &&
4813 ieee802_11_rsnx_capab(sm->rsnxe,
4814 WLAN_RSNX_CAPAB_SECURE_LTF) &&
4815 wpa_auth_set_ltf_keyseed(sm->wpa_auth, sm->addr,
4816 sm->PTK.ltf_keyseed,
4817 sm->PTK.ltf_keyseed_len)) {
4818 wpa_printf(MSG_ERROR,
4819 "WPA: Failed to set LTF keyseed to driver");
4820 wpa_sta_disconnect(sm->wpa_auth, sm->addr,
4821 WLAN_REASON_PREV_AUTH_NOT_VALID);
4822 return;
4823 }
4824#endif /* CONFIG_PASN */
4825
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004826 /* WPA2 send GTK in the 4-way handshake */
4827 secure = 1;
4828 gtk = gsm->GTK[gsm->GN - 1];
4829 gtk_len = gsm->GTK_len;
Hai Shalomfdcde762020-04-02 11:19:20 -07004830 if (conf->disable_gtk ||
Roshan Pius3a1667e2018-07-03 15:17:14 -07004831 sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004832 /*
4833 * Provide unique random GTK to each STA to prevent use
4834 * of GTK in the BSS.
4835 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08004836 if (random_get_bytes(stub_gtk, gtk_len) < 0)
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004837 goto done;
Hai Shaloma20dcd72022-02-04 13:43:00 -08004838 gtk = stub_gtk;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004839 }
Hai Shalomc3565922019-10-28 11:58:20 -07004840 gtkidx = gsm->GN;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004841 _rsc = rsc;
4842 encr = 1;
4843 } else {
4844 /* WPA does not include GTK in msg 3/4 */
4845 secure = 0;
4846 gtk = NULL;
4847 gtk_len = 0;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004848 gtkidx = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004849 _rsc = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004850 if (sm->rx_eapol_key_secure) {
4851 /*
4852 * It looks like Windows 7 supplicant tries to use
4853 * Secure bit in msg 2/4 after having reported Michael
4854 * MIC failure and it then rejects the 4-way handshake
4855 * if msg 3/4 does not set Secure bit. Work around this
4856 * by setting the Secure bit here even in the case of
4857 * WPA if the supplicant used it first.
4858 */
Sunil Raviaf8751c2023-03-29 11:35:17 -07004859 wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm),
4860 LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07004861 "STA used Secure bit in WPA msg 2/4 - set Secure for 3/4 as workaround");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004862 secure = 1;
4863 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004864 }
4865
Hai Shalom74f70d42019-02-11 14:42:39 -08004866 kde_len = wpa_ie_len + ieee80211w_kde_len(sm) + ocv_oci_len(sm);
Hai Shalomfdcde762020-04-02 11:19:20 -07004867
4868 if (sm->use_ext_key_id)
4869 kde_len += 2 + RSN_SELECTOR_LEN + 2;
4870
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004871 if (gtk)
4872 kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004873#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004874 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
4875 kde_len += 2 + PMKID_LEN; /* PMKR1Name into RSN IE */
4876 kde_len += 300; /* FTIE + 2 * TIE */
4877 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004878#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08004879#ifdef CONFIG_P2P
4880 if (WPA_GET_BE32(sm->ip_addr) > 0)
4881 kde_len += 2 + RSN_SELECTOR_LEN + 3 * 4;
4882#endif /* CONFIG_P2P */
Hai Shalomfdcde762020-04-02 11:19:20 -07004883
4884 if (conf->transition_disable)
4885 kde_len += 2 + RSN_SELECTOR_LEN + 1;
4886
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004887#ifdef CONFIG_DPP2
4888 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP)
4889 kde_len += 2 + RSN_SELECTOR_LEN + 2;
4890#endif /* CONFIG_DPP2 */
4891
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004892 kde_len += wpa_auth_ml_kdes_len(sm);
4893
Sunil Ravi7f769292024-07-23 22:21:32 +00004894 if (sm->ssid_protection)
4895 kde_len += 2 + conf->ssid_len;
4896
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004897#ifdef CONFIG_TESTING_OPTIONS
4898 if (conf->eapol_m3_elements)
4899 kde_len += wpabuf_len(conf->eapol_m3_elements);
4900#endif /* CONFIG_TESTING_OPTIONS */
4901
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004902 kde = os_malloc(kde_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07004903 if (!kde)
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004904 goto done;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004905
4906 pos = kde;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004907 if (!is_mld) {
4908 os_memcpy(pos, wpa_ie, wpa_ie_len);
4909 pos += wpa_ie_len;
4910 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004911#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004912 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08004913 int res;
4914 size_t elen;
4915
4916 elen = pos - kde;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004917 res = wpa_insert_pmkid(kde, &elen, sm->pmk_r1_name, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004918 if (res < 0) {
Hai Shalomfdcde762020-04-02 11:19:20 -07004919 wpa_printf(MSG_ERROR,
4920 "FT: Failed to insert PMKR1Name into RSN IE in EAPOL-Key data");
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004921 goto done;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004922 }
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08004923 pos -= wpa_ie_len;
4924 pos += elen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004925 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004926#endif /* CONFIG_IEEE80211R_AP */
Hai Shalomfdcde762020-04-02 11:19:20 -07004927 hdr[1] = 0;
4928
4929 if (sm->use_ext_key_id) {
4930 hdr[0] = sm->keyidx_active & 0x01;
4931 pos = wpa_add_kde(pos, RSN_KEY_DATA_KEYID, hdr, 2, NULL, 0);
4932 }
4933
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004934 if (gtk && !is_mld) {
Hai Shalomc3565922019-10-28 11:58:20 -07004935 hdr[0] = gtkidx & 0x03;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004936 pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
4937 gtk, gtk_len);
4938 }
4939 pos = ieee80211w_kde_add(sm, pos);
Hai Shalom899fcc72020-10-19 14:38:18 -07004940 if (ocv_oci_add(sm, &pos, conf->oci_freq_override_eapol_m3) < 0)
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004941 goto done;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004942
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004943#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004944 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
4945 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004946
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08004947 if (sm->assoc_resp_ftie &&
4948 kde + kde_len - pos >= 2 + sm->assoc_resp_ftie[1]) {
4949 os_memcpy(pos, sm->assoc_resp_ftie,
4950 2 + sm->assoc_resp_ftie[1]);
4951 res = 2 + sm->assoc_resp_ftie[1];
4952 } else {
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00004953 res = wpa_write_ftie(conf, sm->wpa_key_mgmt,
4954 sm->xxkey_len,
Roshan Pius3a1667e2018-07-03 15:17:14 -07004955 conf->r0_key_holder,
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08004956 conf->r0_key_holder_len,
4957 NULL, NULL, pos,
4958 kde + kde_len - pos,
Hai Shalomfdcde762020-04-02 11:19:20 -07004959 NULL, 0, 0);
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08004960 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004961 if (res < 0) {
Hai Shalomfdcde762020-04-02 11:19:20 -07004962 wpa_printf(MSG_ERROR,
4963 "FT: Failed to insert FTIE into EAPOL-Key Key Data");
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004964 goto done;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004965 }
4966 pos += res;
4967
4968 /* TIE[ReassociationDeadline] (TU) */
4969 *pos++ = WLAN_EID_TIMEOUT_INTERVAL;
4970 *pos++ = 5;
4971 *pos++ = WLAN_TIMEOUT_REASSOC_DEADLINE;
4972 WPA_PUT_LE32(pos, conf->reassociation_deadline);
4973 pos += 4;
4974
4975 /* TIE[KeyLifetime] (seconds) */
4976 *pos++ = WLAN_EID_TIMEOUT_INTERVAL;
4977 *pos++ = 5;
4978 *pos++ = WLAN_TIMEOUT_KEY_LIFETIME;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004979 WPA_PUT_LE32(pos, conf->r0_key_lifetime);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004980 pos += 4;
4981 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004982#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08004983#ifdef CONFIG_P2P
4984 if (WPA_GET_BE32(sm->ip_addr) > 0) {
4985 u8 addr[3 * 4];
4986 os_memcpy(addr, sm->ip_addr, 4);
Hai Shalomfdcde762020-04-02 11:19:20 -07004987 os_memcpy(addr + 4, conf->ip_addr_mask, 4);
4988 os_memcpy(addr + 8, conf->ip_addr_go, 4);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08004989 pos = wpa_add_kde(pos, WFA_KEY_DATA_IP_ADDR_ALLOC,
4990 addr, sizeof(addr), NULL, 0);
4991 }
4992#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004993
Hai Shalomfdcde762020-04-02 11:19:20 -07004994 if (conf->transition_disable)
4995 pos = wpa_add_kde(pos, WFA_KEY_DATA_TRANSITION_DISABLE,
4996 &conf->transition_disable, 1, NULL, 0);
4997
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004998#ifdef CONFIG_DPP2
4999 if (DPP_VERSION > 1 && sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP) {
5000 u8 payload[2];
5001
5002 payload[0] = DPP_VERSION; /* Protocol Version */
5003 payload[1] = 0; /* Flags */
5004 if (conf->dpp_pfs == 0)
5005 payload[1] |= DPP_KDE_PFS_ALLOWED;
5006 else if (conf->dpp_pfs == 1)
5007 payload[1] |= DPP_KDE_PFS_ALLOWED |
5008 DPP_KDE_PFS_REQUIRED;
5009 pos = wpa_add_kde(pos, WFA_KEY_DATA_DPP,
5010 payload, sizeof(payload), NULL, 0);
5011 }
5012#endif /* CONFIG_DPP2 */
5013
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005014 pos = wpa_auth_ml_kdes(sm, pos);
Sunil Ravic0f5d412024-09-11 22:12:49 +00005015 if (!pos) {
5016 wpa_printf(MSG_ERROR, "RSN: Failed to add MLO KDEs");
5017 goto done;
5018 }
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005019
Sunil Ravi7f769292024-07-23 22:21:32 +00005020 if (sm->ssid_protection) {
5021 *pos++ = WLAN_EID_SSID;
5022 *pos++ = conf->ssid_len;
5023 os_memcpy(pos, conf->ssid, conf->ssid_len);
5024 pos += conf->ssid_len;
5025 }
5026
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005027#ifdef CONFIG_TESTING_OPTIONS
5028 if (conf->eapol_m3_elements) {
5029 os_memcpy(pos, wpabuf_head(conf->eapol_m3_elements),
5030 wpabuf_len(conf->eapol_m3_elements));
5031 pos += wpabuf_len(conf->eapol_m3_elements);
5032 }
5033
5034 if (conf->eapol_m3_no_encrypt)
5035 encr = 0;
5036#endif /* CONFIG_TESTING_OPTIONS */
5037
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005038 wpa_send_eapol(sm->wpa_auth, sm,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005039 (secure ? WPA_KEY_INFO_SECURE : 0) |
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005040 (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
5041 WPA_KEY_INFO_MIC : 0) |
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005042 WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL |
5043 WPA_KEY_INFO_KEY_TYPE,
Hai Shalomc3565922019-10-28 11:58:20 -07005044 _rsc, sm->ANonce, kde, pos - kde, 0, encr);
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08005045done:
Sunil Ravia04bd252022-05-02 22:54:18 -07005046 bin_clear_free(kde, kde_len);
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08005047 os_free(wpa_ie_buf);
Hai Shalomfdcde762020-04-02 11:19:20 -07005048 os_free(wpa_ie_buf2);
Sunil Ravi7f769292024-07-23 22:21:32 +00005049 os_free(wpa_ie_buf3);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005050}
5051
5052
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005053static int wpa_auth_validate_ml_kdes_m4(struct wpa_state_machine *sm)
5054{
5055#ifdef CONFIG_IEEE80211BE
5056 const struct ieee802_1x_hdr *hdr;
5057 const struct wpa_eapol_key *key;
5058 struct wpa_eapol_ie_parse kde;
5059 const u8 *key_data, *mic;
5060 u16 key_data_length;
5061 size_t mic_len;
5062
5063 if (sm->mld_assoc_link_id < 0)
5064 return 0;
5065
5066 /*
5067 * Note: last_rx_eapol_key length fields have already been validated in
5068 * wpa_receive().
5069 */
5070 mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
5071
5072 hdr = (const struct ieee802_1x_hdr *) sm->last_rx_eapol_key;
5073 key = (const struct wpa_eapol_key *) (hdr + 1);
5074 mic = (const u8 *) (key + 1);
5075 key_data = mic + mic_len + 2;
5076 key_data_length = WPA_GET_BE16(mic + mic_len);
5077 if (key_data_length > sm->last_rx_eapol_key_len - sizeof(*hdr) -
5078 sizeof(*key) - mic_len - 2)
5079 return -1;
5080
5081 if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) {
5082 wpa_auth_vlogger(sm->wpa_auth, wpa_auth_get_spa(sm),
5083 LOGGER_INFO,
5084 "received EAPOL-Key msg 4/4 with invalid Key Data contents");
5085 return -1;
5086 }
5087
5088 /* MLD MAC address must be the same */
5089 if (!kde.mac_addr ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005090 !ether_addr_equal(kde.mac_addr, sm->peer_mld_addr)) {
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005091 wpa_printf(MSG_DEBUG,
5092 "MLD: Mismatching or missing MLD address in EAPOL-Key msg 4/4");
5093 return -1;
5094 }
5095
5096 wpa_printf(MSG_DEBUG, "MLD: MLD address in EAPOL-Key msg 4/4: " MACSTR,
5097 MAC2STR(kde.mac_addr));
5098#endif /* CONFIG_IEEE80211BE */
5099
5100 return 0;
5101}
5102
5103
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005104SM_STATE(WPA_PTK, PTKINITDONE)
5105{
5106 SM_ENTRY_MA(WPA_PTK, PTKINITDONE, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07005107 sm->EAPOLKeyReceived = false;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005108
5109 if (wpa_auth_validate_ml_kdes_m4(sm) < 0) {
5110 wpa_sta_disconnect(sm->wpa_auth, sm->addr,
5111 WLAN_REASON_PREV_AUTH_NOT_VALID);
5112 return;
5113 }
5114
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005115 if (sm->Pair) {
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07005116 enum wpa_alg alg = wpa_cipher_to_alg(sm->pairwise);
5117 int klen = wpa_cipher_key_len(sm->pairwise);
Hai Shalomfdcde762020-04-02 11:19:20 -07005118 int res;
5119
5120 if (sm->use_ext_key_id)
5121 res = wpa_auth_set_key(sm->wpa_auth, 0, 0, sm->addr,
5122 sm->keyidx_active, NULL, 0,
5123 KEY_FLAG_PAIRWISE_RX_TX_MODIFY);
5124 else
5125 res = wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr,
5126 0, sm->PTK.tk, klen,
5127 KEY_FLAG_PAIRWISE_RX_TX);
5128 if (res) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005129 wpa_sta_disconnect(sm->wpa_auth, sm->addr,
5130 WLAN_REASON_PREV_AUTH_NOT_VALID);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005131 return;
5132 }
Sunil Ravi89eba102022-09-13 21:04:37 -07005133
5134#ifdef CONFIG_PASN
5135 if (sm->wpa_auth->conf.secure_ltf &&
5136 ieee802_11_rsnx_capab(sm->rsnxe,
5137 WLAN_RSNX_CAPAB_SECURE_LTF) &&
5138 wpa_auth_set_ltf_keyseed(sm->wpa_auth, sm->addr,
5139 sm->PTK.ltf_keyseed,
5140 sm->PTK.ltf_keyseed_len)) {
5141 wpa_printf(MSG_ERROR,
5142 "WPA: Failed to set LTF keyseed to driver");
5143 wpa_sta_disconnect(sm->wpa_auth, sm->addr,
5144 WLAN_REASON_PREV_AUTH_NOT_VALID);
5145 return;
5146 }
5147#endif /* CONFIG_PASN */
5148
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005149 /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */
Hai Shalome21d4e82020-04-29 16:34:06 -07005150 sm->pairwise_set = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005151
Hai Shalom81f62d82019-07-22 12:10:00 -07005152 wpa_auth_set_ptk_rekey_timer(sm);
Hai Shalom60840252021-02-19 19:02:11 -08005153 wpa_auth_store_ptksa(sm->wpa_auth, sm->addr, sm->pairwise,
5154 dot11RSNAConfigPMKLifetime, &sm->PTK);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005155
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005156 if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
5157 sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP ||
5158 sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005159 wpa_auth_set_eapol(sm->wpa_auth, sm->addr,
5160 WPA_EAPOL_authorized, 1);
5161 }
5162 }
5163
5164 if (0 /* IBSS == TRUE */) {
5165 sm->keycount++;
5166 if (sm->keycount == 2) {
5167 wpa_auth_set_eapol(sm->wpa_auth, sm->addr,
5168 WPA_EAPOL_portValid, 1);
5169 }
5170 } else {
5171 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid,
5172 1);
5173 }
Hai Shalome21d4e82020-04-29 16:34:06 -07005174 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyAvailable,
5175 false);
5176 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyDone, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005177 if (sm->wpa == WPA_VERSION_WPA)
Hai Shalome21d4e82020-04-29 16:34:06 -07005178 sm->PInitAKeys = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005179 else
Hai Shalome21d4e82020-04-29 16:34:06 -07005180 sm->has_GTK = true;
Sunil Raviaf8751c2023-03-29 11:35:17 -07005181 wpa_auth_vlogger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005182 "pairwise key handshake completed (%s)",
5183 sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN");
Hai Shaloma20dcd72022-02-04 13:43:00 -08005184 wpa_msg(sm->wpa_auth->conf.msg_ctx, MSG_INFO, "EAPOL-4WAY-HS-COMPLETED "
5185 MACSTR, MAC2STR(sm->addr));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005186
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005187#ifdef CONFIG_IEEE80211R_AP
Sunil Raviaf8751c2023-03-29 11:35:17 -07005188 wpa_ft_push_pmk_r1(sm->wpa_auth, wpa_auth_get_spa(sm));
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005189#endif /* CONFIG_IEEE80211R_AP */
Sunil Ravia04bd252022-05-02 22:54:18 -07005190
5191 sm->ptkstart_without_success = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005192}
5193
5194
5195SM_STEP(WPA_PTK)
5196{
5197 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
Hai Shalomfdcde762020-04-02 11:19:20 -07005198 struct wpa_auth_config *conf = &wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005199
5200 if (sm->Init)
5201 SM_ENTER(WPA_PTK, INITIALIZE);
5202 else if (sm->Disconnect
5203 /* || FIX: dot11RSNAConfigSALifetime timeout */) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07005204 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005205 "WPA_PTK: sm->Disconnect");
5206 SM_ENTER(WPA_PTK, DISCONNECT);
5207 }
5208 else if (sm->DeauthenticationRequest)
5209 SM_ENTER(WPA_PTK, DISCONNECTED);
5210 else if (sm->AuthenticationRequest)
5211 SM_ENTER(WPA_PTK, AUTHENTICATION);
5212 else if (sm->ReAuthenticationRequest)
5213 SM_ENTER(WPA_PTK, AUTHENTICATION2);
Jouni Malinen1420a892017-10-01 12:32:57 +03005214 else if (sm->PTKRequest) {
5215 if (wpa_auth_sm_ptk_update(sm) < 0)
5216 SM_ENTER(WPA_PTK, DISCONNECTED);
5217 else
5218 SM_ENTER(WPA_PTK, PTKSTART);
5219 } else switch (sm->wpa_ptk_state) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005220 case WPA_PTK_INITIALIZE:
5221 break;
5222 case WPA_PTK_DISCONNECT:
5223 SM_ENTER(WPA_PTK, DISCONNECTED);
5224 break;
5225 case WPA_PTK_DISCONNECTED:
5226 SM_ENTER(WPA_PTK, INITIALIZE);
5227 break;
5228 case WPA_PTK_AUTHENTICATION:
5229 SM_ENTER(WPA_PTK, AUTHENTICATION2);
5230 break;
5231 case WPA_PTK_AUTHENTICATION2:
5232 if (wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) &&
Hai Shalomfdcde762020-04-02 11:19:20 -07005233 wpa_auth_get_eapol(wpa_auth, sm->addr,
Hai Shalome21d4e82020-04-29 16:34:06 -07005234 WPA_EAPOL_keyRun))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005235 SM_ENTER(WPA_PTK, INITPMK);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005236 else if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
5237 sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005238 /* FIX: && 802.1X::keyRun */)
5239 SM_ENTER(WPA_PTK, INITPSK);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005240 else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP)
5241 SM_ENTER(WPA_PTK, INITPMK);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005242 break;
5243 case WPA_PTK_INITPMK:
Hai Shalomfdcde762020-04-02 11:19:20 -07005244 if (wpa_auth_get_eapol(wpa_auth, sm->addr,
Hai Shalome21d4e82020-04-29 16:34:06 -07005245 WPA_EAPOL_keyAvailable)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005246 SM_ENTER(WPA_PTK, PTKSTART);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005247#ifdef CONFIG_DPP
5248 } else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP && sm->pmksa) {
5249 SM_ENTER(WPA_PTK, PTKSTART);
5250#endif /* CONFIG_DPP */
5251 } else {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005252 wpa_auth->dot11RSNA4WayHandshakeFailures++;
Sunil Raviaf8751c2023-03-29 11:35:17 -07005253 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
5254 LOGGER_INFO,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005255 "INITPMK - keyAvailable = false");
5256 SM_ENTER(WPA_PTK, DISCONNECT);
5257 }
5258 break;
5259 case WPA_PTK_INITPSK:
Hai Shalomfdcde762020-04-02 11:19:20 -07005260 if (wpa_auth_get_psk(wpa_auth, sm->addr, sm->p2p_dev_addr,
Hai Shalom021b0b52019-04-10 11:17:58 -07005261 NULL, NULL, NULL)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005262 SM_ENTER(WPA_PTK, PTKSTART);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005263#ifdef CONFIG_SAE
5264 } else if (wpa_auth_uses_sae(sm) && sm->pmksa) {
5265 SM_ENTER(WPA_PTK, PTKSTART);
5266#endif /* CONFIG_SAE */
Sunil Ravia04bd252022-05-02 22:54:18 -07005267 } else if (wpa_key_mgmt_wpa_psk_no_sae(sm->wpa_key_mgmt) &&
5268 wpa_auth->conf.radius_psk) {
5269 wpa_printf(MSG_DEBUG,
5270 "INITPSK: No PSK yet available for STA - use RADIUS later");
5271 SM_ENTER(WPA_PTK, PTKSTART);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005272 } else {
Sunil Raviaf8751c2023-03-29 11:35:17 -07005273 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
5274 LOGGER_INFO,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005275 "no PSK configured for the STA");
5276 wpa_auth->dot11RSNA4WayHandshakeFailures++;
5277 SM_ENTER(WPA_PTK, DISCONNECT);
5278 }
5279 break;
5280 case WPA_PTK_PTKSTART:
5281 if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest &&
5282 sm->EAPOLKeyPairwise)
5283 SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING);
Hai Shalomfdcde762020-04-02 11:19:20 -07005284 else if (sm->TimeoutCtr > conf->wpa_pairwise_update_count) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005285 wpa_auth->dot11RSNA4WayHandshakeFailures++;
Sunil Raviaf8751c2023-03-29 11:35:17 -07005286 wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
5287 LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07005288 "PTKSTART: Retry limit %u reached",
5289 conf->wpa_pairwise_update_count);
Hai Shalome21d4e82020-04-29 16:34:06 -07005290 sm->disconnect_reason =
5291 WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005292 SM_ENTER(WPA_PTK, DISCONNECT);
5293 } else if (sm->TimeoutEvt)
5294 SM_ENTER(WPA_PTK, PTKSTART);
5295 break;
5296 case WPA_PTK_PTKCALCNEGOTIATING:
5297 if (sm->MICVerified)
5298 SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING2);
5299 else if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest &&
5300 sm->EAPOLKeyPairwise)
5301 SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING);
5302 else if (sm->TimeoutEvt)
5303 SM_ENTER(WPA_PTK, PTKSTART);
5304 break;
5305 case WPA_PTK_PTKCALCNEGOTIATING2:
5306 SM_ENTER(WPA_PTK, PTKINITNEGOTIATING);
5307 break;
5308 case WPA_PTK_PTKINITNEGOTIATING:
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005309 if (sm->update_snonce)
5310 SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING);
5311 else if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest &&
5312 sm->EAPOLKeyPairwise && sm->MICVerified)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005313 SM_ENTER(WPA_PTK, PTKINITDONE);
5314 else if (sm->TimeoutCtr >
Hai Shalomfdcde762020-04-02 11:19:20 -07005315 conf->wpa_pairwise_update_count ||
5316 (conf->wpa_disable_eapol_key_retries &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005317 sm->TimeoutCtr > 1)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005318 wpa_auth->dot11RSNA4WayHandshakeFailures++;
Sunil Raviaf8751c2023-03-29 11:35:17 -07005319 wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
5320 LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07005321 "PTKINITNEGOTIATING: Retry limit %u reached",
5322 conf->wpa_pairwise_update_count);
Hai Shalome21d4e82020-04-29 16:34:06 -07005323 sm->disconnect_reason =
5324 WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005325 SM_ENTER(WPA_PTK, DISCONNECT);
5326 } else if (sm->TimeoutEvt)
5327 SM_ENTER(WPA_PTK, PTKINITNEGOTIATING);
5328 break;
5329 case WPA_PTK_PTKINITDONE:
5330 break;
5331 }
5332}
5333
5334
5335SM_STATE(WPA_PTK_GROUP, IDLE)
5336{
5337 SM_ENTRY_MA(WPA_PTK_GROUP, IDLE, wpa_ptk_group);
5338 if (sm->Init) {
5339 /* Init flag is not cleared here, so avoid busy
5340 * loop by claiming nothing changed. */
Hai Shalome21d4e82020-04-29 16:34:06 -07005341 sm->changed = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005342 }
5343 sm->GTimeoutCtr = 0;
5344}
5345
5346
5347SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING)
5348{
5349 u8 rsc[WPA_KEY_RSC_LEN];
5350 struct wpa_group *gsm = sm->group;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005351 const u8 *kde = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005352 u8 *kde_buf = NULL, *pos, hdr[2];
Sunil Ravia04bd252022-05-02 22:54:18 -07005353 size_t kde_len = 0;
Hai Shaloma20dcd72022-02-04 13:43:00 -08005354 u8 *gtk, stub_gtk[32];
Hai Shalomfdcde762020-04-02 11:19:20 -07005355 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005356 bool is_mld = false;
5357
5358#ifdef CONFIG_IEEE80211BE
5359 is_mld = sm->mld_assoc_link_id >= 0;
5360#endif /* CONFIG_IEEE80211BE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005361
5362 SM_ENTRY_MA(WPA_PTK_GROUP, REKEYNEGOTIATING, wpa_ptk_group);
5363
5364 sm->GTimeoutCtr++;
Hai Shalomfdcde762020-04-02 11:19:20 -07005365 if (conf->wpa_disable_eapol_key_retries && sm->GTimeoutCtr > 1) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005366 /* Do not allow retransmission of EAPOL-Key group msg 1/2 */
5367 return;
5368 }
Hai Shalomfdcde762020-04-02 11:19:20 -07005369 if (sm->GTimeoutCtr > conf->wpa_group_update_count) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005370 /* No point in sending the EAPOL-Key - we will disconnect
5371 * immediately following this. */
5372 return;
5373 }
5374
5375 if (sm->wpa == WPA_VERSION_WPA)
Hai Shalome21d4e82020-04-29 16:34:06 -07005376 sm->PInitAKeys = false;
5377 sm->TimeoutEvt = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005378 /* Send EAPOL(1, 1, 1, !Pair, G, RSC, GNonce, MIC(PTK), GTK[GN]) */
5379 os_memset(rsc, 0, WPA_KEY_RSC_LEN);
5380 if (gsm->wpa_group_state == WPA_GROUP_SETKEYSDONE)
5381 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc);
Sunil Raviaf8751c2023-03-29 11:35:17 -07005382 wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005383 "sending 1/2 msg of Group Key Handshake");
5384
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005385 gtk = gsm->GTK[gsm->GN - 1];
Hai Shalomfdcde762020-04-02 11:19:20 -07005386 if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005387 /*
5388 * Provide unique random GTK to each STA to prevent use
5389 * of GTK in the BSS.
5390 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08005391 if (random_get_bytes(stub_gtk, gsm->GTK_len) < 0)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005392 return;
Hai Shaloma20dcd72022-02-04 13:43:00 -08005393 gtk = stub_gtk;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005394 }
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005395
5396 if (sm->wpa == WPA_VERSION_WPA2 && !is_mld) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005397 kde_len = 2 + RSN_SELECTOR_LEN + 2 + gsm->GTK_len +
Hai Shalom74f70d42019-02-11 14:42:39 -08005398 ieee80211w_kde_len(sm) + ocv_oci_len(sm);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005399 kde_buf = os_malloc(kde_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07005400 if (!kde_buf)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005401 return;
5402
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005403 kde = pos = kde_buf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005404 hdr[0] = gsm->GN & 0x03;
5405 hdr[1] = 0;
5406 pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005407 gtk, gsm->GTK_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005408 pos = ieee80211w_kde_add(sm, pos);
Hai Shalom899fcc72020-10-19 14:38:18 -07005409 if (ocv_oci_add(sm, &pos,
5410 conf->oci_freq_override_eapol_g1) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -08005411 os_free(kde_buf);
5412 return;
5413 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005414 kde_len = pos - kde;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005415#ifdef CONFIG_IEEE80211BE
5416 } else if (sm->wpa == WPA_VERSION_WPA2 && is_mld) {
5417 kde_len = wpa_auth_ml_group_kdes_len(sm);
5418 if (kde_len) {
5419 kde_buf = os_malloc(kde_len);
5420 if (!kde_buf)
5421 return;
5422
5423 kde = pos = kde_buf;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005424 pos = wpa_auth_ml_group_kdes(sm, pos);
5425 kde_len = pos - kde_buf;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005426 }
5427#endif /* CONFIG_IEEE80211BE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005428 } else {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005429 kde = gtk;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005430 kde_len = gsm->GTK_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005431 }
5432
5433 wpa_send_eapol(sm->wpa_auth, sm,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005434 WPA_KEY_INFO_SECURE |
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005435 (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
5436 WPA_KEY_INFO_MIC : 0) |
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005437 WPA_KEY_INFO_ACK |
5438 (!sm->Pair ? WPA_KEY_INFO_INSTALL : 0),
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005439 rsc, NULL, kde, kde_len, gsm->GN, 1);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005440
Sunil Ravia04bd252022-05-02 22:54:18 -07005441 bin_clear_free(kde_buf, kde_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005442}
5443
5444
5445SM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED)
5446{
Hai Shalom74f70d42019-02-11 14:42:39 -08005447 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
Hai Shalomfdcde762020-04-02 11:19:20 -07005448#ifdef CONFIG_OCV
Hai Shalom74f70d42019-02-11 14:42:39 -08005449 const u8 *key_data, *mic;
5450 struct ieee802_1x_hdr *hdr;
5451 struct wpa_eapol_key *key;
5452 struct wpa_eapol_ie_parse kde;
5453 size_t mic_len;
5454 u16 key_data_length;
5455#endif /* CONFIG_OCV */
5456
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005457 SM_ENTRY_MA(WPA_PTK_GROUP, REKEYESTABLISHED, wpa_ptk_group);
Hai Shalome21d4e82020-04-29 16:34:06 -07005458 sm->EAPOLKeyReceived = false;
Hai Shalom74f70d42019-02-11 14:42:39 -08005459
5460#ifdef CONFIG_OCV
5461 mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
5462
5463 /*
5464 * Note: last_rx_eapol_key length fields have already been validated in
5465 * wpa_receive().
5466 */
5467 hdr = (struct ieee802_1x_hdr *) sm->last_rx_eapol_key;
5468 key = (struct wpa_eapol_key *) (hdr + 1);
5469 mic = (u8 *) (key + 1);
5470 key_data = mic + mic_len + 2;
5471 key_data_length = WPA_GET_BE16(mic + mic_len);
5472 if (key_data_length > sm->last_rx_eapol_key_len - sizeof(*hdr) -
5473 sizeof(*key) - mic_len - 2)
5474 return;
5475
5476 if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07005477 wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
Hai Shalom74f70d42019-02-11 14:42:39 -08005478 "received EAPOL-Key group msg 2/2 with invalid Key Data contents");
5479 return;
5480 }
5481
5482 if (wpa_auth_uses_ocv(sm)) {
5483 struct wpa_channel_info ci;
5484 int tx_chanwidth;
5485 int tx_seg1_idx;
5486
5487 if (wpa_channel_info(wpa_auth, &ci) != 0) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07005488 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
5489 LOGGER_INFO,
Hai Shalom899fcc72020-10-19 14:38:18 -07005490 "Failed to get channel info to validate received OCI in EAPOL-Key group 2/2");
Hai Shalom74f70d42019-02-11 14:42:39 -08005491 return;
5492 }
5493
5494 if (get_sta_tx_parameters(sm,
5495 channel_width_to_int(ci.chanwidth),
5496 ci.seg1_idx, &tx_chanwidth,
5497 &tx_seg1_idx) < 0)
5498 return;
5499
5500 if (ocv_verify_tx_params(kde.oci, kde.oci_len, &ci,
Hai Shalom899fcc72020-10-19 14:38:18 -07005501 tx_chanwidth, tx_seg1_idx) !=
5502 OCI_SUCCESS) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07005503 wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
5504 LOGGER_INFO,
Hai Shalom899fcc72020-10-19 14:38:18 -07005505 "OCV failed: %s", ocv_errorstr);
5506 if (wpa_auth->conf.msg_ctx)
5507 wpa_msg(wpa_auth->conf.msg_ctx, MSG_INFO,
5508 OCV_FAILURE "addr=" MACSTR
5509 " frame=eapol-key-g2 error=%s",
Sunil Raviaf8751c2023-03-29 11:35:17 -07005510 MAC2STR(wpa_auth_get_spa(sm)),
5511 ocv_errorstr);
Hai Shalom74f70d42019-02-11 14:42:39 -08005512 return;
5513 }
5514 }
5515#endif /* CONFIG_OCV */
5516
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005517 if (sm->GUpdateStationKeys)
Sunil Ravi7f769292024-07-23 22:21:32 +00005518 wpa_gkeydone_sta(sm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005519 sm->GTimeoutCtr = 0;
5520 /* FIX: MLME.SetProtection.Request(TA, Tx_Rx) */
Sunil Raviaf8751c2023-03-29 11:35:17 -07005521 wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005522 "group key handshake completed (%s)",
5523 sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN");
Hai Shalome21d4e82020-04-29 16:34:06 -07005524 sm->has_GTK = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005525}
5526
5527
5528SM_STATE(WPA_PTK_GROUP, KEYERROR)
5529{
5530 SM_ENTRY_MA(WPA_PTK_GROUP, KEYERROR, wpa_ptk_group);
5531 if (sm->GUpdateStationKeys)
Sunil Ravi7f769292024-07-23 22:21:32 +00005532 wpa_gkeydone_sta(sm);
5533 if (sm->wpa_auth->conf.no_disconnect_on_group_keyerror &&
5534 sm->wpa == WPA_VERSION_WPA2) {
5535 wpa_auth_vlogger(sm->wpa_auth, wpa_auth_get_spa(sm),
5536 LOGGER_DEBUG,
5537 "group key handshake failed after %u tries - allow STA to remain connected",
5538 sm->wpa_auth->conf.wpa_group_update_count);
5539 return;
5540 }
Hai Shalome21d4e82020-04-29 16:34:06 -07005541 sm->Disconnect = true;
5542 sm->disconnect_reason = WLAN_REASON_GROUP_KEY_UPDATE_TIMEOUT;
Sunil Raviaf8751c2023-03-29 11:35:17 -07005543 wpa_auth_vlogger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005544 "group key handshake failed (%s) after %u tries",
5545 sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN",
5546 sm->wpa_auth->conf.wpa_group_update_count);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005547}
5548
5549
5550SM_STEP(WPA_PTK_GROUP)
5551{
5552 if (sm->Init || sm->PtkGroupInit) {
5553 SM_ENTER(WPA_PTK_GROUP, IDLE);
Hai Shalome21d4e82020-04-29 16:34:06 -07005554 sm->PtkGroupInit = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005555 } else switch (sm->wpa_ptk_group_state) {
5556 case WPA_PTK_GROUP_IDLE:
5557 if (sm->GUpdateStationKeys ||
5558 (sm->wpa == WPA_VERSION_WPA && sm->PInitAKeys))
5559 SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING);
5560 break;
5561 case WPA_PTK_GROUP_REKEYNEGOTIATING:
5562 if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest &&
5563 !sm->EAPOLKeyPairwise && sm->MICVerified)
5564 SM_ENTER(WPA_PTK_GROUP, REKEYESTABLISHED);
5565 else if (sm->GTimeoutCtr >
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005566 sm->wpa_auth->conf.wpa_group_update_count ||
5567 (sm->wpa_auth->conf.wpa_disable_eapol_key_retries &&
5568 sm->GTimeoutCtr > 1))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005569 SM_ENTER(WPA_PTK_GROUP, KEYERROR);
5570 else if (sm->TimeoutEvt)
5571 SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING);
5572 break;
5573 case WPA_PTK_GROUP_KEYERROR:
5574 SM_ENTER(WPA_PTK_GROUP, IDLE);
5575 break;
5576 case WPA_PTK_GROUP_REKEYESTABLISHED:
5577 SM_ENTER(WPA_PTK_GROUP, IDLE);
5578 break;
5579 }
5580}
5581
5582
5583static int wpa_gtk_update(struct wpa_authenticator *wpa_auth,
5584 struct wpa_group *group)
5585{
Hai Shalomfdcde762020-04-02 11:19:20 -07005586 struct wpa_auth_config *conf = &wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005587 int ret = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07005588 size_t len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005589
5590 os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
5591 inc_byte_array(group->Counter, WPA_NONCE_LEN);
5592 if (wpa_gmk_to_gtk(group->GMK, "Group key expansion",
5593 wpa_auth->addr, group->GNonce,
5594 group->GTK[group->GN - 1], group->GTK_len) < 0)
5595 ret = -1;
5596 wpa_hexdump_key(MSG_DEBUG, "GTK",
5597 group->GTK[group->GN - 1], group->GTK_len);
5598
Hai Shalomfdcde762020-04-02 11:19:20 -07005599 if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
5600 len = wpa_cipher_key_len(conf->group_mgmt_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005601 os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
5602 inc_byte_array(group->Counter, WPA_NONCE_LEN);
5603 if (wpa_gmk_to_gtk(group->GMK, "IGTK key expansion",
5604 wpa_auth->addr, group->GNonce,
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07005605 group->IGTK[group->GN_igtk - 4], len) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005606 ret = -1;
5607 wpa_hexdump_key(MSG_DEBUG, "IGTK",
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07005608 group->IGTK[group->GN_igtk - 4], len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005609 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005610
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005611 if (!wpa_auth->non_tx_beacon_prot &&
5612 conf->ieee80211w == NO_MGMT_FRAME_PROTECTION)
5613 return ret;
5614 if (!conf->beacon_prot)
5615 return ret;
5616
5617 if (wpa_auth->conf.tx_bss_auth) {
5618 group = wpa_auth->conf.tx_bss_auth->group;
5619 if (group->bigtk_set)
5620 return ret;
5621 wpa_printf(MSG_DEBUG, "Set up BIGTK for TX BSS");
Hai Shalomfdcde762020-04-02 11:19:20 -07005622 }
5623
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005624 len = wpa_cipher_key_len(conf->group_mgmt_cipher);
5625 os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
5626 inc_byte_array(group->Counter, WPA_NONCE_LEN);
5627 if (wpa_gmk_to_gtk(group->GMK, "BIGTK key expansion",
5628 wpa_auth->addr, group->GNonce,
5629 group->BIGTK[group->GN_bigtk - 6], len) < 0)
5630 return -1;
5631 group->bigtk_set = true;
5632 wpa_hexdump_key(MSG_DEBUG, "BIGTK",
5633 group->BIGTK[group->GN_bigtk - 6], len);
5634
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005635 return ret;
5636}
5637
5638
5639static void wpa_group_gtk_init(struct wpa_authenticator *wpa_auth,
5640 struct wpa_group *group)
5641{
Hai Shalomfdcde762020-04-02 11:19:20 -07005642 wpa_printf(MSG_DEBUG,
5643 "WPA: group state machine entering state GTK_INIT (VLAN-ID %d)",
5644 group->vlan_id);
Hai Shalome21d4e82020-04-29 16:34:06 -07005645 group->changed = false; /* GInit is not cleared here; avoid loop */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005646 group->wpa_group_state = WPA_GROUP_GTK_INIT;
5647
5648 /* GTK[0..N] = 0 */
5649 os_memset(group->GTK, 0, sizeof(group->GTK));
5650 group->GN = 1;
5651 group->GM = 2;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005652 group->GN_igtk = 4;
5653 group->GM_igtk = 5;
Hai Shalomfdcde762020-04-02 11:19:20 -07005654 group->GN_bigtk = 6;
5655 group->GM_bigtk = 7;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005656 /* GTK[GN] = CalcGTK() */
5657 wpa_gtk_update(wpa_auth, group);
5658}
5659
5660
5661static int wpa_group_update_sta(struct wpa_state_machine *sm, void *ctx)
5662{
Sunil Ravic0f5d412024-09-11 22:12:49 +00005663 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
5664 struct wpa_group *group = sm->group;
5665#ifdef CONFIG_IEEE80211BE
5666 int link_id;
5667
5668 for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
5669 if (!sm->mld_links[link_id].valid)
5670 continue;
5671 if (sm->mld_links[link_id].wpa_auth &&
5672 sm->mld_links[link_id].wpa_auth->group == ctx) {
5673 group = sm->mld_links[link_id].wpa_auth->group;
5674 wpa_auth = sm->mld_links[link_id].wpa_auth;
5675 break;
5676 }
5677 }
5678#endif /* CONFIG_IEEE80211BE */
5679
5680 if (ctx && ctx != group)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005681 return 0;
5682
Sunil Ravic0f5d412024-09-11 22:12:49 +00005683#ifdef CONFIG_IEEE80211BE
5684 /* For ML STA, run rekey on the association link and send G1 with keys
5685 * for all links. This is based on assumption that MLD level
5686 * Authenticator updates group keys on all affiliated links in one shot
5687 * and not independently or concurrently for separate links. */
5688 if (sm->mld_assoc_link_id >= 0 &&
5689 sm->mld_assoc_link_id != wpa_auth->link_id)
5690 return 0;
5691#endif /* CONFIG_IEEE80211BE */
5692
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005693 if (sm->wpa_ptk_state != WPA_PTK_PTKINITDONE) {
Sunil Ravic0f5d412024-09-11 22:12:49 +00005694 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
Sunil Raviaf8751c2023-03-29 11:35:17 -07005695 LOGGER_DEBUG,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005696 "Not in PTKINITDONE; skip Group Key update");
Hai Shalome21d4e82020-04-29 16:34:06 -07005697 sm->GUpdateStationKeys = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005698 return 0;
5699 }
5700 if (sm->GUpdateStationKeys) {
5701 /*
5702 * This should not really happen, so add a debug log entry.
5703 * Since we clear the GKeyDoneStations before the loop, the
5704 * station needs to be counted here anyway.
5705 */
Sunil Ravic0f5d412024-09-11 22:12:49 +00005706 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
Sunil Raviaf8751c2023-03-29 11:35:17 -07005707 LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07005708 "GUpdateStationKeys was already set when marking station for GTK rekeying");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005709 }
5710
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005711 /* Do not rekey GTK/IGTK when STA is in WNM-Sleep Mode */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005712 if (sm->is_wnmsleep)
5713 return 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005714
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005715 sm->group->GKeyDoneStations++;
Sunil Ravic0f5d412024-09-11 22:12:49 +00005716#ifdef CONFIG_IEEE80211BE
5717 for_each_sm_auth(sm, link_id)
5718 sm->mld_links[link_id].wpa_auth->group->GKeyDoneStations++;
5719#endif /* CONFIG_IEEE80211BE */
5720
Hai Shalome21d4e82020-04-29 16:34:06 -07005721 sm->GUpdateStationKeys = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005722
5723 wpa_sm_step(sm);
5724 return 0;
5725}
5726
5727
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005728#ifdef CONFIG_WNM_AP
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005729/* update GTK when exiting WNM-Sleep Mode */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005730void wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm)
5731{
Hai Shalomfdcde762020-04-02 11:19:20 -07005732 if (!sm || sm->is_wnmsleep)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005733 return;
5734
5735 wpa_group_update_sta(sm, NULL);
5736}
5737
5738
5739void wpa_set_wnmsleep(struct wpa_state_machine *sm, int flag)
5740{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005741 if (sm)
5742 sm->is_wnmsleep = !!flag;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005743}
5744
5745
5746int wpa_wnmsleep_gtk_subelem(struct wpa_state_machine *sm, u8 *pos)
5747{
Hai Shalom899fcc72020-10-19 14:38:18 -07005748 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005749 struct wpa_group *gsm = sm->group;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005750 u8 *start = pos;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005751
5752 /*
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005753 * GTK subelement:
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005754 * Sub-elem ID[1] | Length[1] | Key Info[2] | Key Length[1] | RSC[8] |
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005755 * Key[5..32]
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005756 */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005757 *pos++ = WNM_SLEEP_SUBELEM_GTK;
5758 *pos++ = 11 + gsm->GTK_len;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005759 /* Key ID in B0-B1 of Key Info */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005760 WPA_PUT_LE16(pos, gsm->GN & 0x03);
5761 pos += 2;
5762 *pos++ = gsm->GTK_len;
5763 if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, pos) != 0)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005764 return 0;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005765 pos += 8;
5766 os_memcpy(pos, gsm->GTK[gsm->GN - 1], gsm->GTK_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07005767 if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
5768 /*
5769 * Provide unique random GTK to each STA to prevent use
5770 * of GTK in the BSS.
5771 */
5772 if (random_get_bytes(pos, gsm->GTK_len) < 0)
5773 return 0;
5774 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005775 pos += gsm->GTK_len;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005776
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005777 wpa_printf(MSG_DEBUG, "WNM: GTK Key ID %u in WNM-Sleep Mode exit",
5778 gsm->GN);
5779 wpa_hexdump_key(MSG_DEBUG, "WNM: GTK in WNM-Sleep Mode exit",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005780 gsm->GTK[gsm->GN - 1], gsm->GTK_len);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005781
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005782 return pos - start;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005783}
5784
5785
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005786int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos)
5787{
Hai Shalom899fcc72020-10-19 14:38:18 -07005788 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005789 struct wpa_group *gsm = sm->group;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005790 u8 *start = pos;
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07005791 size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005792
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005793 /*
5794 * IGTK subelement:
5795 * Sub-elem ID[1] | Length[1] | KeyID[2] | PN[6] | Key[16]
5796 */
5797 *pos++ = WNM_SLEEP_SUBELEM_IGTK;
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07005798 *pos++ = 2 + 6 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005799 WPA_PUT_LE16(pos, gsm->GN_igtk);
5800 pos += 2;
5801 if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, pos) != 0)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005802 return 0;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005803 pos += 6;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005804
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07005805 os_memcpy(pos, gsm->IGTK[gsm->GN_igtk - 4], len);
Hai Shalom899fcc72020-10-19 14:38:18 -07005806 if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
5807 /*
5808 * Provide unique random IGTK to each STA to prevent use
5809 * of IGTK in the BSS.
5810 */
5811 if (random_get_bytes(pos, len) < 0)
5812 return 0;
5813 }
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07005814 pos += len;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005815
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005816 wpa_printf(MSG_DEBUG, "WNM: IGTK Key ID %u in WNM-Sleep Mode exit",
5817 gsm->GN_igtk);
5818 wpa_hexdump_key(MSG_DEBUG, "WNM: IGTK in WNM-Sleep Mode exit",
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07005819 gsm->IGTK[gsm->GN_igtk - 4], len);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005820
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005821 return pos - start;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005822}
Hai Shalomc3565922019-10-28 11:58:20 -07005823
Hai Shalomfdcde762020-04-02 11:19:20 -07005824
5825int wpa_wnmsleep_bigtk_subelem(struct wpa_state_machine *sm, u8 *pos)
5826{
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005827 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
5828 struct wpa_group *gsm = wpa_auth->group;
Hai Shalomfdcde762020-04-02 11:19:20 -07005829 u8 *start = pos;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005830 size_t len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher);
Hai Shalomfdcde762020-04-02 11:19:20 -07005831
5832 /*
5833 * BIGTK subelement:
5834 * Sub-elem ID[1] | Length[1] | KeyID[2] | PN[6] | Key[16]
5835 */
5836 *pos++ = WNM_SLEEP_SUBELEM_BIGTK;
5837 *pos++ = 2 + 6 + len;
5838 WPA_PUT_LE16(pos, gsm->GN_bigtk);
5839 pos += 2;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005840 if (wpa_auth_get_seqnum(wpa_auth, NULL, gsm->GN_bigtk, pos) != 0)
Hai Shalomfdcde762020-04-02 11:19:20 -07005841 return 0;
5842 pos += 6;
5843
5844 os_memcpy(pos, gsm->BIGTK[gsm->GN_bigtk - 6], len);
Hai Shalom899fcc72020-10-19 14:38:18 -07005845 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
5846 /*
5847 * Provide unique random BIGTK to each STA to prevent use
5848 * of BIGTK in the BSS.
5849 */
5850 if (random_get_bytes(pos, len) < 0)
5851 return 0;
5852 }
Hai Shalomfdcde762020-04-02 11:19:20 -07005853 pos += len;
5854
5855 wpa_printf(MSG_DEBUG, "WNM: BIGTK Key ID %u in WNM-Sleep Mode exit",
5856 gsm->GN_bigtk);
5857 wpa_hexdump_key(MSG_DEBUG, "WNM: BIGTK in WNM-Sleep Mode exit",
Hai Shaloma20dcd72022-02-04 13:43:00 -08005858 gsm->BIGTK[gsm->GN_bigtk - 6], len);
Hai Shalomfdcde762020-04-02 11:19:20 -07005859
5860 return pos - start;
5861}
5862
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005863#endif /* CONFIG_WNM_AP */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005864
5865
Sunil Ravi7f769292024-07-23 22:21:32 +00005866static void wpa_group_update_gtk(struct wpa_authenticator *wpa_auth,
5867 struct wpa_group *group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005868{
5869 int tmp;
5870
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005871 tmp = group->GM;
5872 group->GM = group->GN;
5873 group->GN = tmp;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005874 tmp = group->GM_igtk;
5875 group->GM_igtk = group->GN_igtk;
5876 group->GN_igtk = tmp;
Hai Shalomfdcde762020-04-02 11:19:20 -07005877 tmp = group->GM_bigtk;
5878 group->GM_bigtk = group->GN_bigtk;
5879 group->GN_bigtk = tmp;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005880 /* "GKeyDoneStations = GNoStations" is done in more robust way by
5881 * counting the STAs that are marked with GUpdateStationKeys instead of
5882 * including all STAs that could be in not-yet-completed state. */
5883 wpa_gtk_update(wpa_auth, group);
Sunil Ravi7f769292024-07-23 22:21:32 +00005884}
5885
5886
5887static void wpa_group_setkeys(struct wpa_authenticator *wpa_auth,
5888 struct wpa_group *group)
5889{
5890 wpa_printf(MSG_DEBUG,
5891 "WPA: group state machine entering state SETKEYS (VLAN-ID %d)",
5892 group->vlan_id);
5893 group->changed = true;
5894 group->wpa_group_state = WPA_GROUP_SETKEYS;
5895 group->GTKReKey = false;
5896
5897#ifdef CONFIG_IEEE80211BE
5898 if (wpa_auth->is_ml)
5899 goto skip_update;
5900#endif /* CONFIG_IEEE80211BE */
5901
5902 wpa_group_update_gtk(wpa_auth, group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005903
5904 if (group->GKeyDoneStations) {
Hai Shalomfdcde762020-04-02 11:19:20 -07005905 wpa_printf(MSG_DEBUG,
5906 "wpa_group_setkeys: Unexpected GKeyDoneStations=%d when starting new GTK rekey",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005907 group->GKeyDoneStations);
5908 group->GKeyDoneStations = 0;
5909 }
Sunil Ravi7f769292024-07-23 22:21:32 +00005910
5911#ifdef CONFIG_IEEE80211BE
5912skip_update:
5913#endif /* CONFIG_IEEE80211BE */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005914 wpa_auth_for_each_sta(wpa_auth, wpa_group_update_sta, group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005915 wpa_printf(MSG_DEBUG, "wpa_group_setkeys: GKeyDoneStations=%d",
5916 group->GKeyDoneStations);
5917}
5918
5919
5920static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth,
5921 struct wpa_group *group)
5922{
Hai Shalomfdcde762020-04-02 11:19:20 -07005923 struct wpa_auth_config *conf = &wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005924 int ret = 0;
5925
5926 if (wpa_auth_set_key(wpa_auth, group->vlan_id,
Hai Shalomfdcde762020-04-02 11:19:20 -07005927 wpa_cipher_to_alg(conf->wpa_group),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005928 broadcast_ether_addr, group->GN,
Hai Shalomfdcde762020-04-02 11:19:20 -07005929 group->GTK[group->GN - 1], group->GTK_len,
5930 KEY_FLAG_GROUP_TX_DEFAULT) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005931 ret = -1;
5932
Hai Shalomfdcde762020-04-02 11:19:20 -07005933 if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07005934 enum wpa_alg alg;
5935 size_t len;
5936
Hai Shalomfdcde762020-04-02 11:19:20 -07005937 alg = wpa_cipher_to_alg(conf->group_mgmt_cipher);
5938 len = wpa_cipher_key_len(conf->group_mgmt_cipher);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07005939
5940 if (ret == 0 &&
5941 wpa_auth_set_key(wpa_auth, group->vlan_id, alg,
5942 broadcast_ether_addr, group->GN_igtk,
Hai Shalomfdcde762020-04-02 11:19:20 -07005943 group->IGTK[group->GN_igtk - 4], len,
5944 KEY_FLAG_GROUP_TX_DEFAULT) < 0)
5945 ret = -1;
5946
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005947 if (ret || !conf->beacon_prot)
5948 return ret;
5949 if (wpa_auth->conf.tx_bss_auth) {
5950 wpa_auth = wpa_auth->conf.tx_bss_auth;
5951 group = wpa_auth->group;
5952 if (!group->bigtk_set || group->bigtk_configured)
5953 return ret;
5954 }
5955 if (wpa_auth_set_key(wpa_auth, group->vlan_id, alg,
Hai Shalomfdcde762020-04-02 11:19:20 -07005956 broadcast_ether_addr, group->GN_bigtk,
5957 group->BIGTK[group->GN_bigtk - 6], len,
5958 KEY_FLAG_GROUP_TX_DEFAULT) < 0)
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07005959 ret = -1;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005960 else
5961 group->bigtk_configured = true;
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07005962 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005963
5964 return ret;
5965}
5966
5967
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005968static int wpa_group_disconnect_cb(struct wpa_state_machine *sm, void *ctx)
5969{
5970 if (sm->group == ctx) {
5971 wpa_printf(MSG_DEBUG, "WPA: Mark STA " MACSTR
Hai Shalomfdcde762020-04-02 11:19:20 -07005972 " for disconnection due to fatal failure",
Sunil Raviaf8751c2023-03-29 11:35:17 -07005973 MAC2STR(wpa_auth_get_spa(sm)));
Hai Shalome21d4e82020-04-29 16:34:06 -07005974 sm->Disconnect = true;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005975 }
5976
5977 return 0;
5978}
5979
5980
5981static void wpa_group_fatal_failure(struct wpa_authenticator *wpa_auth,
5982 struct wpa_group *group)
5983{
Hai Shalomfdcde762020-04-02 11:19:20 -07005984 wpa_printf(MSG_DEBUG,
5985 "WPA: group state machine entering state FATAL_FAILURE");
Hai Shalome21d4e82020-04-29 16:34:06 -07005986 group->changed = true;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005987 group->wpa_group_state = WPA_GROUP_FATAL_FAILURE;
5988 wpa_auth_for_each_sta(wpa_auth, wpa_group_disconnect_cb, group);
5989}
5990
5991
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005992static int wpa_group_setkeysdone(struct wpa_authenticator *wpa_auth,
5993 struct wpa_group *group)
5994{
Hai Shalomfdcde762020-04-02 11:19:20 -07005995 wpa_printf(MSG_DEBUG,
5996 "WPA: group state machine entering state SETKEYSDONE (VLAN-ID %d)",
5997 group->vlan_id);
Hai Shalome21d4e82020-04-29 16:34:06 -07005998 group->changed = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005999 group->wpa_group_state = WPA_GROUP_SETKEYSDONE;
6000
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006001 if (wpa_group_config_group_keys(wpa_auth, group) < 0) {
6002 wpa_group_fatal_failure(wpa_auth, group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006003 return -1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006004 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006005
6006 return 0;
6007}
6008
6009
6010static void wpa_group_sm_step(struct wpa_authenticator *wpa_auth,
6011 struct wpa_group *group)
6012{
6013 if (group->GInit) {
6014 wpa_group_gtk_init(wpa_auth, group);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006015 } else if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) {
6016 /* Do not allow group operations */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006017 } else if (group->wpa_group_state == WPA_GROUP_GTK_INIT &&
6018 group->GTKAuthenticator) {
6019 wpa_group_setkeysdone(wpa_auth, group);
6020 } else if (group->wpa_group_state == WPA_GROUP_SETKEYSDONE &&
6021 group->GTKReKey) {
6022 wpa_group_setkeys(wpa_auth, group);
6023 } else if (group->wpa_group_state == WPA_GROUP_SETKEYS) {
6024 if (group->GKeyDoneStations == 0)
6025 wpa_group_setkeysdone(wpa_auth, group);
6026 else if (group->GTKReKey)
6027 wpa_group_setkeys(wpa_auth, group);
6028 }
6029}
6030
6031
Sunil Ravi7f769292024-07-23 22:21:32 +00006032static void wpa_clear_changed(struct wpa_state_machine *sm)
6033{
6034#ifdef CONFIG_IEEE80211BE
6035 int link_id;
6036#endif /* CONFIG_IEEE80211BE */
6037
6038 sm->changed = false;
6039 sm->wpa_auth->group->changed = false;
6040
6041#ifdef CONFIG_IEEE80211BE
6042 for_each_sm_auth(sm, link_id)
6043 sm->mld_links[link_id].wpa_auth->group->changed = false;
6044#endif /* CONFIG_IEEE80211BE */
6045}
6046
6047
6048static void wpa_group_sm_step_links(struct wpa_state_machine *sm)
6049{
6050#ifdef CONFIG_IEEE80211BE
6051 int link_id;
6052#endif /* CONFIG_IEEE80211BE */
6053
6054 if (!sm || !sm->wpa_auth)
6055 return;
6056 wpa_group_sm_step(sm->wpa_auth, sm->wpa_auth->group);
6057
6058#ifdef CONFIG_IEEE80211BE
6059 for_each_sm_auth(sm, link_id) {
6060 wpa_group_sm_step(sm->mld_links[link_id].wpa_auth,
6061 sm->mld_links[link_id].wpa_auth->group);
6062 }
6063#endif /* CONFIG_IEEE80211BE */
6064}
6065
6066
6067static bool wpa_group_sm_changed(struct wpa_state_machine *sm)
6068{
6069#ifdef CONFIG_IEEE80211BE
6070 int link_id;
6071#endif /* CONFIG_IEEE80211BE */
6072 bool changed;
6073
6074 if (!sm || !sm->wpa_auth)
6075 return false;
6076 changed = sm->wpa_auth->group->changed;
6077
6078#ifdef CONFIG_IEEE80211BE
6079 for_each_sm_auth(sm, link_id)
6080 changed |= sm->mld_links[link_id].wpa_auth->group->changed;
6081#endif /* CONFIG_IEEE80211BE */
6082
6083 return changed;
6084}
6085
6086
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006087static int wpa_sm_step(struct wpa_state_machine *sm)
6088{
Hai Shalomfdcde762020-04-02 11:19:20 -07006089 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006090 return 0;
6091
6092 if (sm->in_step_loop) {
6093 /* This should not happen, but if it does, make sure we do not
6094 * end up freeing the state machine too early by exiting the
6095 * recursive call. */
6096 wpa_printf(MSG_ERROR, "WPA: wpa_sm_step() called recursively");
6097 return 0;
6098 }
6099
6100 sm->in_step_loop = 1;
6101 do {
6102 if (sm->pending_deinit)
6103 break;
6104
Sunil Ravi7f769292024-07-23 22:21:32 +00006105 wpa_clear_changed(sm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006106
6107 SM_STEP_RUN(WPA_PTK);
6108 if (sm->pending_deinit)
6109 break;
6110 SM_STEP_RUN(WPA_PTK_GROUP);
6111 if (sm->pending_deinit)
6112 break;
Sunil Ravi7f769292024-07-23 22:21:32 +00006113 wpa_group_sm_step_links(sm);
6114 } while (sm->changed || wpa_group_sm_changed(sm));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006115 sm->in_step_loop = 0;
6116
6117 if (sm->pending_deinit) {
Hai Shalomfdcde762020-04-02 11:19:20 -07006118 wpa_printf(MSG_DEBUG,
6119 "WPA: Completing pending STA state machine deinit for "
Sunil Raviaf8751c2023-03-29 11:35:17 -07006120 MACSTR, MAC2STR(wpa_auth_get_spa(sm)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006121 wpa_free_sta_sm(sm);
6122 return 1;
6123 }
6124 return 0;
6125}
6126
6127
6128static void wpa_sm_call_step(void *eloop_ctx, void *timeout_ctx)
6129{
6130 struct wpa_state_machine *sm = eloop_ctx;
6131 wpa_sm_step(sm);
6132}
6133
6134
6135void wpa_auth_sm_notify(struct wpa_state_machine *sm)
6136{
Hai Shalomfdcde762020-04-02 11:19:20 -07006137 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006138 return;
6139 eloop_register_timeout(0, 0, wpa_sm_call_step, sm, NULL);
6140}
6141
6142
6143void wpa_gtk_rekey(struct wpa_authenticator *wpa_auth)
6144{
6145 int tmp, i;
6146 struct wpa_group *group;
6147
Hai Shalomfdcde762020-04-02 11:19:20 -07006148 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006149 return;
6150
6151 group = wpa_auth->group;
6152
6153 for (i = 0; i < 2; i++) {
6154 tmp = group->GM;
6155 group->GM = group->GN;
6156 group->GN = tmp;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006157 tmp = group->GM_igtk;
6158 group->GM_igtk = group->GN_igtk;
6159 group->GN_igtk = tmp;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00006160 if (!wpa_auth->conf.tx_bss_auth) {
6161 tmp = group->GM_bigtk;
6162 group->GM_bigtk = group->GN_bigtk;
6163 group->GN_bigtk = tmp;
6164 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006165 wpa_gtk_update(wpa_auth, group);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006166 wpa_group_config_group_keys(wpa_auth, group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006167 }
6168}
6169
6170
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07006171static const char * wpa_bool_txt(int val)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006172{
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07006173 return val ? "TRUE" : "FALSE";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006174}
6175
6176
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006177#define RSN_SUITE "%02x-%02x-%02x-%d"
6178#define RSN_SUITE_ARG(s) \
6179((s) >> 24) & 0xff, ((s) >> 16) & 0xff, ((s) >> 8) & 0xff, (s) & 0xff
6180
6181int wpa_get_mib(struct wpa_authenticator *wpa_auth, char *buf, size_t buflen)
6182{
Hai Shalomfdcde762020-04-02 11:19:20 -07006183 struct wpa_auth_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006184 int len = 0, ret;
6185 char pmkid_txt[PMKID_LEN * 2 + 1];
6186#ifdef CONFIG_RSN_PREAUTH
6187 const int preauth = 1;
6188#else /* CONFIG_RSN_PREAUTH */
6189 const int preauth = 0;
6190#endif /* CONFIG_RSN_PREAUTH */
6191
Hai Shalomfdcde762020-04-02 11:19:20 -07006192 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006193 return len;
Hai Shalomfdcde762020-04-02 11:19:20 -07006194 conf = &wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006195
6196 ret = os_snprintf(buf + len, buflen - len,
6197 "dot11RSNAOptionImplemented=TRUE\n"
6198 "dot11RSNAPreauthenticationImplemented=%s\n"
6199 "dot11RSNAEnabled=%s\n"
6200 "dot11RSNAPreauthenticationEnabled=%s\n",
6201 wpa_bool_txt(preauth),
Hai Shalomfdcde762020-04-02 11:19:20 -07006202 wpa_bool_txt(conf->wpa & WPA_PROTO_RSN),
6203 wpa_bool_txt(conf->rsn_preauth));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006204 if (os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006205 return len;
6206 len += ret;
6207
6208 wpa_snprintf_hex(pmkid_txt, sizeof(pmkid_txt),
6209 wpa_auth->dot11RSNAPMKIDUsed, PMKID_LEN);
6210
6211 ret = os_snprintf(
6212 buf + len, buflen - len,
6213 "dot11RSNAConfigVersion=%u\n"
6214 "dot11RSNAConfigPairwiseKeysSupported=9999\n"
6215 /* FIX: dot11RSNAConfigGroupCipher */
6216 /* FIX: dot11RSNAConfigGroupRekeyMethod */
6217 /* FIX: dot11RSNAConfigGroupRekeyTime */
6218 /* FIX: dot11RSNAConfigGroupRekeyPackets */
6219 "dot11RSNAConfigGroupRekeyStrict=%u\n"
6220 "dot11RSNAConfigGroupUpdateCount=%u\n"
6221 "dot11RSNAConfigPairwiseUpdateCount=%u\n"
6222 "dot11RSNAConfigGroupCipherSize=%u\n"
6223 "dot11RSNAConfigPMKLifetime=%u\n"
6224 "dot11RSNAConfigPMKReauthThreshold=%u\n"
6225 "dot11RSNAConfigNumberOfPTKSAReplayCounters=0\n"
6226 "dot11RSNAConfigSATimeout=%u\n"
6227 "dot11RSNAAuthenticationSuiteSelected=" RSN_SUITE "\n"
6228 "dot11RSNAPairwiseCipherSelected=" RSN_SUITE "\n"
6229 "dot11RSNAGroupCipherSelected=" RSN_SUITE "\n"
6230 "dot11RSNAPMKIDUsed=%s\n"
6231 "dot11RSNAAuthenticationSuiteRequested=" RSN_SUITE "\n"
6232 "dot11RSNAPairwiseCipherRequested=" RSN_SUITE "\n"
6233 "dot11RSNAGroupCipherRequested=" RSN_SUITE "\n"
6234 "dot11RSNATKIPCounterMeasuresInvoked=%u\n"
6235 "dot11RSNA4WayHandshakeFailures=%u\n"
6236 "dot11RSNAConfigNumberOfGTKSAReplayCounters=0\n",
6237 RSN_VERSION,
Hai Shalomfdcde762020-04-02 11:19:20 -07006238 !!conf->wpa_strict_rekey,
6239 conf->wpa_group_update_count,
6240 conf->wpa_pairwise_update_count,
6241 wpa_cipher_key_len(conf->wpa_group) * 8,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006242 dot11RSNAConfigPMKLifetime,
6243 dot11RSNAConfigPMKReauthThreshold,
6244 dot11RSNAConfigSATimeout,
6245 RSN_SUITE_ARG(wpa_auth->dot11RSNAAuthenticationSuiteSelected),
6246 RSN_SUITE_ARG(wpa_auth->dot11RSNAPairwiseCipherSelected),
6247 RSN_SUITE_ARG(wpa_auth->dot11RSNAGroupCipherSelected),
6248 pmkid_txt,
6249 RSN_SUITE_ARG(wpa_auth->dot11RSNAAuthenticationSuiteRequested),
6250 RSN_SUITE_ARG(wpa_auth->dot11RSNAPairwiseCipherRequested),
6251 RSN_SUITE_ARG(wpa_auth->dot11RSNAGroupCipherRequested),
6252 wpa_auth->dot11RSNATKIPCounterMeasuresInvoked,
6253 wpa_auth->dot11RSNA4WayHandshakeFailures);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006254 if (os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006255 return len;
6256 len += ret;
6257
6258 /* TODO: dot11RSNAConfigPairwiseCiphersTable */
6259 /* TODO: dot11RSNAConfigAuthenticationSuitesTable */
6260
6261 /* Private MIB */
6262 ret = os_snprintf(buf + len, buflen - len, "hostapdWPAGroupState=%d\n",
6263 wpa_auth->group->wpa_group_state);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006264 if (os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006265 return len;
6266 len += ret;
6267
6268 return len;
6269}
6270
6271
6272int wpa_get_mib_sta(struct wpa_state_machine *sm, char *buf, size_t buflen)
6273{
6274 int len = 0, ret;
6275 u32 pairwise = 0;
6276
Hai Shalomfdcde762020-04-02 11:19:20 -07006277 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006278 return 0;
6279
6280 /* TODO: FF-FF-FF-FF-FF-FF entry for broadcast/multicast stats */
6281
6282 /* dot11RSNAStatsEntry */
6283
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07006284 pairwise = wpa_cipher_to_suite(sm->wpa == WPA_VERSION_WPA2 ?
6285 WPA_PROTO_RSN : WPA_PROTO_WPA,
6286 sm->pairwise);
6287 if (pairwise == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006288 return 0;
6289
6290 ret = os_snprintf(
6291 buf + len, buflen - len,
6292 /* TODO: dot11RSNAStatsIndex */
6293 "dot11RSNAStatsSTAAddress=" MACSTR "\n"
6294 "dot11RSNAStatsVersion=1\n"
6295 "dot11RSNAStatsSelectedPairwiseCipher=" RSN_SUITE "\n"
6296 /* TODO: dot11RSNAStatsTKIPICVErrors */
6297 "dot11RSNAStatsTKIPLocalMICFailures=%u\n"
6298 "dot11RSNAStatsTKIPRemoteMICFailures=%u\n"
6299 /* TODO: dot11RSNAStatsCCMPReplays */
6300 /* TODO: dot11RSNAStatsCCMPDecryptErrors */
6301 /* TODO: dot11RSNAStatsTKIPReplays */,
6302 MAC2STR(sm->addr),
6303 RSN_SUITE_ARG(pairwise),
6304 sm->dot11RSNAStatsTKIPLocalMICFailures,
6305 sm->dot11RSNAStatsTKIPRemoteMICFailures);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006306 if (os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006307 return len;
6308 len += ret;
6309
6310 /* Private MIB */
6311 ret = os_snprintf(buf + len, buflen - len,
Hai Shalomc3565922019-10-28 11:58:20 -07006312 "wpa=%d\n"
6313 "AKMSuiteSelector=" RSN_SUITE "\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006314 "hostapdWPAPTKState=%d\n"
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00006315 "hostapdWPAPTKGroupState=%d\n"
6316 "hostapdMFPR=%d\n",
Hai Shalomc3565922019-10-28 11:58:20 -07006317 sm->wpa,
6318 RSN_SUITE_ARG(wpa_akm_to_suite(sm->wpa_key_mgmt)),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006319 sm->wpa_ptk_state,
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00006320 sm->wpa_ptk_group_state,
6321 sm->mfpr);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006322 if (os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006323 return len;
6324 len += ret;
6325
6326 return len;
6327}
6328
6329
6330void wpa_auth_countermeasures_start(struct wpa_authenticator *wpa_auth)
6331{
6332 if (wpa_auth)
6333 wpa_auth->dot11RSNATKIPCounterMeasuresInvoked++;
6334}
6335
6336
6337int wpa_auth_pairwise_set(struct wpa_state_machine *sm)
6338{
6339 return sm && sm->pairwise_set;
6340}
6341
6342
6343int wpa_auth_get_pairwise(struct wpa_state_machine *sm)
6344{
6345 return sm->pairwise;
6346}
6347
6348
Hai Shalom74f70d42019-02-11 14:42:39 -08006349const u8 * wpa_auth_get_pmk(struct wpa_state_machine *sm, int *len)
6350{
6351 if (!sm)
6352 return NULL;
6353 *len = sm->pmk_len;
6354 return sm->PMK;
6355}
6356
6357
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00006358const u8 * wpa_auth_get_dpp_pkhash(struct wpa_state_machine *sm)
6359{
6360 if (!sm || !sm->pmksa)
6361 return NULL;
6362 return sm->pmksa->dpp_pkhash;
6363}
6364
6365
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006366int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm)
6367{
Hai Shalomfdcde762020-04-02 11:19:20 -07006368 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006369 return -1;
6370 return sm->wpa_key_mgmt;
6371}
6372
6373
6374int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm)
6375{
Hai Shalomfdcde762020-04-02 11:19:20 -07006376 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006377 return 0;
6378 return sm->wpa;
6379}
6380
6381
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02006382int wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm)
6383{
6384 if (!sm || !wpa_key_mgmt_ft(sm->wpa_key_mgmt))
6385 return 0;
6386 return sm->tk_already_set;
6387}
6388
6389
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006390int wpa_auth_sta_fils_tk_already_set(struct wpa_state_machine *sm)
6391{
6392 if (!sm || !wpa_key_mgmt_fils(sm->wpa_key_mgmt))
6393 return 0;
6394 return sm->tk_already_set;
6395}
6396
6397
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006398int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm,
6399 struct rsn_pmksa_cache_entry *entry)
6400{
Hai Shalomfdcde762020-04-02 11:19:20 -07006401 if (!sm || sm->pmksa != entry)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006402 return -1;
6403 sm->pmksa = NULL;
6404 return 0;
6405}
6406
6407
6408struct rsn_pmksa_cache_entry *
6409wpa_auth_sta_get_pmksa(struct wpa_state_machine *sm)
6410{
6411 return sm ? sm->pmksa : NULL;
6412}
6413
6414
6415void wpa_auth_sta_local_mic_failure_report(struct wpa_state_machine *sm)
6416{
6417 if (sm)
6418 sm->dot11RSNAStatsTKIPLocalMICFailures++;
6419}
6420
6421
6422const u8 * wpa_auth_get_wpa_ie(struct wpa_authenticator *wpa_auth, size_t *len)
6423{
Hai Shalomfdcde762020-04-02 11:19:20 -07006424 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006425 return NULL;
6426 *len = wpa_auth->wpa_ie_len;
6427 return wpa_auth->wpa_ie;
6428}
6429
6430
6431int wpa_auth_pmksa_add(struct wpa_state_machine *sm, const u8 *pmk,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006432 unsigned int pmk_len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006433 int session_timeout, struct eapol_state_machine *eapol)
6434{
Hai Shalomfdcde762020-04-02 11:19:20 -07006435 if (!sm || sm->wpa != WPA_VERSION_WPA2 ||
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07006436 sm->wpa_auth->conf.disable_pmksa_caching)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006437 return -1;
6438
Hai Shalom81f62d82019-07-22 12:10:00 -07006439#ifdef CONFIG_IEEE80211R_AP
6440 if (pmk_len >= 2 * PMK_LEN && wpa_key_mgmt_ft(sm->wpa_key_mgmt) &&
6441 wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) &&
6442 !wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) {
6443 /* Cache MPMK/XXKey instead of initial part from MSK */
6444 pmk = pmk + PMK_LEN;
6445 pmk_len = PMK_LEN;
6446 } else
6447#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006448 if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006449 if (pmk_len > PMK_LEN_SUITE_B_192)
6450 pmk_len = PMK_LEN_SUITE_B_192;
6451 } else if (pmk_len > PMK_LEN) {
6452 pmk_len = PMK_LEN;
6453 }
6454
Hai Shalom81f62d82019-07-22 12:10:00 -07006455 wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK", pmk, pmk_len);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006456 if (pmksa_cache_auth_add(sm->wpa_auth->pmksa, pmk, pmk_len, NULL,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08006457 sm->PTK.kck, sm->PTK.kck_len,
Sunil Raviaf8751c2023-03-29 11:35:17 -07006458 wpa_auth_get_aa(sm),
6459 wpa_auth_get_spa(sm), session_timeout,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006460 eapol, sm->wpa_key_mgmt))
6461 return 0;
6462
6463 return -1;
6464}
6465
6466
6467int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth,
6468 const u8 *pmk, size_t len, const u8 *sta_addr,
6469 int session_timeout,
6470 struct eapol_state_machine *eapol)
6471{
Hai Shalomfdcde762020-04-02 11:19:20 -07006472 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006473 return -1;
6474
Hai Shalom81f62d82019-07-22 12:10:00 -07006475 wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK from preauth", pmk, len);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006476 if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, len, NULL,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006477 NULL, 0,
6478 wpa_auth->addr,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006479 sta_addr, session_timeout, eapol,
6480 WPA_KEY_MGMT_IEEE8021X))
6481 return 0;
6482
6483 return -1;
6484}
6485
6486
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006487int wpa_auth_pmksa_add_sae(struct wpa_authenticator *wpa_auth, const u8 *addr,
Sunil Ravi89eba102022-09-13 21:04:37 -07006488 const u8 *pmk, size_t pmk_len, const u8 *pmkid,
6489 int akmp)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006490{
6491 if (wpa_auth->conf.disable_pmksa_caching)
6492 return -1;
6493
Sunil Ravi89eba102022-09-13 21:04:37 -07006494 wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK from SAE", pmk, pmk_len);
6495 if (!akmp)
6496 akmp = WPA_KEY_MGMT_SAE;
6497 if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, pmk_len, pmkid,
6498 NULL, 0, wpa_auth->addr, addr, 0, NULL, akmp))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006499 return 0;
6500
6501 return -1;
6502}
6503
6504
Roshan Pius3a1667e2018-07-03 15:17:14 -07006505void wpa_auth_add_sae_pmkid(struct wpa_state_machine *sm, const u8 *pmkid)
6506{
6507 os_memcpy(sm->pmkid, pmkid, PMKID_LEN);
6508 sm->pmkid_set = 1;
6509}
6510
6511
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006512int wpa_auth_pmksa_add2(struct wpa_authenticator *wpa_auth, const u8 *addr,
6513 const u8 *pmk, size_t pmk_len, const u8 *pmkid,
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00006514 int session_timeout, int akmp, const u8 *dpp_pkhash)
6515{
6516 struct rsn_pmksa_cache_entry *entry;
6517
Sunil Ravib0ac25f2024-07-12 01:42:03 +00006518 if (!wpa_auth || wpa_auth->conf.disable_pmksa_caching)
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00006519 return -1;
6520
6521 wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK (3)", pmk, PMK_LEN);
6522 entry = pmksa_cache_auth_add(wpa_auth->pmksa, pmk, pmk_len, pmkid,
6523 NULL, 0, wpa_auth->addr, addr, session_timeout,
6524 NULL, akmp);
6525 if (!entry)
6526 return -1;
6527
6528 if (dpp_pkhash)
6529 entry->dpp_pkhash = os_memdup(dpp_pkhash, SHA256_MAC_LEN);
6530
6531 return 0;
6532}
6533
6534
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07006535void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth,
6536 const u8 *sta_addr)
6537{
6538 struct rsn_pmksa_cache_entry *pmksa;
6539
Hai Shalomfdcde762020-04-02 11:19:20 -07006540 if (!wpa_auth || !wpa_auth->pmksa)
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07006541 return;
6542 pmksa = pmksa_cache_auth_get(wpa_auth->pmksa, sta_addr, NULL);
6543 if (pmksa) {
6544 wpa_printf(MSG_DEBUG, "WPA: Remove PMKSA cache entry for "
6545 MACSTR " based on request", MAC2STR(sta_addr));
6546 pmksa_cache_free_entry(wpa_auth->pmksa, pmksa);
6547 }
6548}
6549
6550
Dmitry Shmidte4663042016-04-04 10:07:49 -07006551int wpa_auth_pmksa_list(struct wpa_authenticator *wpa_auth, char *buf,
6552 size_t len)
6553{
6554 if (!wpa_auth || !wpa_auth->pmksa)
6555 return 0;
6556 return pmksa_cache_auth_list(wpa_auth->pmksa, buf, len);
6557}
6558
6559
6560void wpa_auth_pmksa_flush(struct wpa_authenticator *wpa_auth)
6561{
6562 if (wpa_auth && wpa_auth->pmksa)
6563 pmksa_cache_auth_flush(wpa_auth->pmksa);
6564}
6565
6566
Paul Stewart092955c2017-02-06 09:13:09 -08006567#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
6568#ifdef CONFIG_MESH
6569
6570int wpa_auth_pmksa_list_mesh(struct wpa_authenticator *wpa_auth, const u8 *addr,
6571 char *buf, size_t len)
6572{
6573 if (!wpa_auth || !wpa_auth->pmksa)
6574 return 0;
6575
6576 return pmksa_cache_auth_list_mesh(wpa_auth->pmksa, addr, buf, len);
6577}
6578
6579
6580struct rsn_pmksa_cache_entry *
6581wpa_auth_pmksa_create_entry(const u8 *aa, const u8 *spa, const u8 *pmk,
Sunil Ravi89eba102022-09-13 21:04:37 -07006582 size_t pmk_len, int akmp,
Paul Stewart092955c2017-02-06 09:13:09 -08006583 const u8 *pmkid, int expiration)
6584{
6585 struct rsn_pmksa_cache_entry *entry;
6586 struct os_reltime now;
6587
Sunil Ravi89eba102022-09-13 21:04:37 -07006588 entry = pmksa_cache_auth_create_entry(pmk, pmk_len, pmkid, NULL, 0, aa,
6589 spa, 0, NULL, akmp);
Paul Stewart092955c2017-02-06 09:13:09 -08006590 if (!entry)
6591 return NULL;
6592
6593 os_get_reltime(&now);
6594 entry->expiration = now.sec + expiration;
6595 return entry;
6596}
6597
6598
6599int wpa_auth_pmksa_add_entry(struct wpa_authenticator *wpa_auth,
6600 struct rsn_pmksa_cache_entry *entry)
6601{
6602 int ret;
6603
6604 if (!wpa_auth || !wpa_auth->pmksa)
6605 return -1;
6606
6607 ret = pmksa_cache_auth_add_entry(wpa_auth->pmksa, entry);
6608 if (ret < 0)
6609 wpa_printf(MSG_DEBUG,
6610 "RSN: Failed to store external PMKSA cache for "
6611 MACSTR, MAC2STR(entry->spa));
6612
6613 return ret;
6614}
6615
6616#endif /* CONFIG_MESH */
6617#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
6618
6619
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00006620struct rsn_pmksa_cache *
6621wpa_auth_get_pmksa_cache(struct wpa_authenticator *wpa_auth)
6622{
6623 if (!wpa_auth || !wpa_auth->pmksa)
6624 return NULL;
6625 return wpa_auth->pmksa;
6626}
6627
6628
Dmitry Shmidte4663042016-04-04 10:07:49 -07006629struct rsn_pmksa_cache_entry *
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08006630wpa_auth_pmksa_get(struct wpa_authenticator *wpa_auth, const u8 *sta_addr,
6631 const u8 *pmkid)
Dmitry Shmidte4663042016-04-04 10:07:49 -07006632{
6633 if (!wpa_auth || !wpa_auth->pmksa)
6634 return NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08006635 return pmksa_cache_auth_get(wpa_auth->pmksa, sta_addr, pmkid);
Dmitry Shmidte4663042016-04-04 10:07:49 -07006636}
6637
6638
Sunil Ravi79e6c4f2025-01-04 00:47:06 +00006639int wpa_auth_pmksa_get_pmk(struct wpa_authenticator *wpa_auth,
6640 const u8 *sta_addr, const u8 **pmk, size_t *pmk_len,
6641 const u8 **pmkid)
6642{
6643 struct rsn_pmksa_cache_entry *pmksa;
6644
6645 pmksa = wpa_auth_pmksa_get(wpa_auth, sta_addr, NULL);
6646 if (!pmksa) {
6647 wpa_printf(MSG_DEBUG, "RSN: Failed to get PMKSA for " MACSTR,
6648 MAC2STR(sta_addr));
6649 return -1;
6650 }
6651
6652 *pmk = pmksa->pmk;
6653 *pmk_len = pmksa->pmk_len;
6654 *pmkid = pmksa->pmkid;
6655 return 0;
6656}
6657
6658
Dmitry Shmidte4663042016-04-04 10:07:49 -07006659void wpa_auth_pmksa_set_to_sm(struct rsn_pmksa_cache_entry *pmksa,
6660 struct wpa_state_machine *sm,
6661 struct wpa_authenticator *wpa_auth,
Sunil Ravib0ac25f2024-07-12 01:42:03 +00006662 u8 *pmkid, u8 *pmk, size_t *pmk_len)
Dmitry Shmidte4663042016-04-04 10:07:49 -07006663{
6664 if (!sm)
6665 return;
6666
6667 sm->pmksa = pmksa;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00006668 os_memcpy(pmk, pmksa->pmk, pmksa->pmk_len);
6669 *pmk_len = pmksa->pmk_len;
Dmitry Shmidte4663042016-04-04 10:07:49 -07006670 os_memcpy(pmkid, pmksa->pmkid, PMKID_LEN);
6671 os_memcpy(wpa_auth->dot11RSNAPMKIDUsed, pmksa->pmkid, PMKID_LEN);
6672}
6673
6674
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07006675/*
6676 * Remove and free the group from wpa_authenticator. This is triggered by a
6677 * callback to make sure nobody is currently iterating the group list while it
6678 * gets modified.
6679 */
6680static void wpa_group_free(struct wpa_authenticator *wpa_auth,
6681 struct wpa_group *group)
6682{
6683 struct wpa_group *prev = wpa_auth->group;
6684
6685 wpa_printf(MSG_DEBUG, "WPA: Remove group state machine for VLAN-ID %d",
6686 group->vlan_id);
6687
6688 while (prev) {
6689 if (prev->next == group) {
6690 /* This never frees the special first group as needed */
6691 prev->next = group->next;
6692 os_free(group);
6693 break;
6694 }
6695 prev = prev->next;
6696 }
6697
6698}
6699
6700
6701/* Increase the reference counter for group */
6702static void wpa_group_get(struct wpa_authenticator *wpa_auth,
6703 struct wpa_group *group)
6704{
6705 /* Skip the special first group */
6706 if (wpa_auth->group == group)
6707 return;
6708
6709 group->references++;
6710}
6711
6712
6713/* Decrease the reference counter and maybe free the group */
6714static void wpa_group_put(struct wpa_authenticator *wpa_auth,
6715 struct wpa_group *group)
6716{
6717 /* Skip the special first group */
6718 if (wpa_auth->group == group)
6719 return;
6720
6721 group->references--;
6722 if (group->references)
6723 return;
6724 wpa_group_free(wpa_auth, group);
6725}
6726
6727
6728/*
6729 * Add a group that has its references counter set to zero. Caller needs to
6730 * call wpa_group_get() on the return value to mark the entry in use.
6731 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006732static struct wpa_group *
6733wpa_auth_add_group(struct wpa_authenticator *wpa_auth, int vlan_id)
6734{
6735 struct wpa_group *group;
6736
Hai Shalomfdcde762020-04-02 11:19:20 -07006737 if (!wpa_auth || !wpa_auth->group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006738 return NULL;
6739
6740 wpa_printf(MSG_DEBUG, "WPA: Add group state machine for VLAN-ID %d",
6741 vlan_id);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006742 group = wpa_group_init(wpa_auth, vlan_id, 0);
Hai Shalomfdcde762020-04-02 11:19:20 -07006743 if (!group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006744 return NULL;
6745
6746 group->next = wpa_auth->group->next;
6747 wpa_auth->group->next = group;
6748
6749 return group;
6750}
6751
6752
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006753/*
6754 * Enforce that the group state machine for the VLAN is running, increase
6755 * reference counter as interface is up. References might have been increased
6756 * even if a negative value is returned.
6757 * Returns: -1 on error (group missing, group already failed); otherwise, 0
6758 */
6759int wpa_auth_ensure_group(struct wpa_authenticator *wpa_auth, int vlan_id)
6760{
6761 struct wpa_group *group;
6762
Hai Shalomfdcde762020-04-02 11:19:20 -07006763 if (!wpa_auth)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006764 return 0;
6765
6766 group = wpa_auth->group;
6767 while (group) {
6768 if (group->vlan_id == vlan_id)
6769 break;
6770 group = group->next;
6771 }
6772
Hai Shalomfdcde762020-04-02 11:19:20 -07006773 if (!group) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006774 group = wpa_auth_add_group(wpa_auth, vlan_id);
Hai Shalomfdcde762020-04-02 11:19:20 -07006775 if (!group)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006776 return -1;
6777 }
6778
6779 wpa_printf(MSG_DEBUG,
6780 "WPA: Ensure group state machine running for VLAN ID %d",
6781 vlan_id);
6782
6783 wpa_group_get(wpa_auth, group);
6784 group->num_setup_iface++;
6785
6786 if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
6787 return -1;
6788
6789 return 0;
6790}
6791
6792
6793/*
6794 * Decrease reference counter, expected to be zero afterwards.
6795 * returns: -1 on error (group not found, group in fail state)
6796 * -2 if wpa_group is still referenced
6797 * 0 else
6798 */
6799int wpa_auth_release_group(struct wpa_authenticator *wpa_auth, int vlan_id)
6800{
6801 struct wpa_group *group;
6802 int ret = 0;
6803
Hai Shalomfdcde762020-04-02 11:19:20 -07006804 if (!wpa_auth)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006805 return 0;
6806
6807 group = wpa_auth->group;
6808 while (group) {
6809 if (group->vlan_id == vlan_id)
6810 break;
6811 group = group->next;
6812 }
6813
Hai Shalomfdcde762020-04-02 11:19:20 -07006814 if (!group)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006815 return -1;
6816
6817 wpa_printf(MSG_DEBUG,
6818 "WPA: Try stopping group state machine for VLAN ID %d",
6819 vlan_id);
6820
6821 if (group->num_setup_iface <= 0) {
6822 wpa_printf(MSG_ERROR,
6823 "WPA: wpa_auth_release_group called more often than wpa_auth_ensure_group for VLAN ID %d, skipping.",
6824 vlan_id);
6825 return -1;
6826 }
6827 group->num_setup_iface--;
6828
6829 if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
6830 ret = -1;
6831
6832 if (group->references > 1) {
6833 wpa_printf(MSG_DEBUG,
6834 "WPA: Cannot stop group state machine for VLAN ID %d as references are still hold",
6835 vlan_id);
6836 ret = -2;
6837 }
6838
6839 wpa_group_put(wpa_auth, group);
6840
6841 return ret;
6842}
6843
6844
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006845int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id)
6846{
6847 struct wpa_group *group;
6848
Hai Shalomfdcde762020-04-02 11:19:20 -07006849 if (!sm || !sm->wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006850 return 0;
6851
6852 group = sm->wpa_auth->group;
6853 while (group) {
6854 if (group->vlan_id == vlan_id)
6855 break;
6856 group = group->next;
6857 }
6858
Hai Shalomfdcde762020-04-02 11:19:20 -07006859 if (!group) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006860 group = wpa_auth_add_group(sm->wpa_auth, vlan_id);
Hai Shalomfdcde762020-04-02 11:19:20 -07006861 if (!group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006862 return -1;
6863 }
6864
6865 if (sm->group == group)
6866 return 0;
6867
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006868 if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
6869 return -1;
6870
Hai Shalomfdcde762020-04-02 11:19:20 -07006871 wpa_printf(MSG_DEBUG, "WPA: Moving STA " MACSTR
6872 " to use group state machine for VLAN ID %d",
Sunil Raviaf8751c2023-03-29 11:35:17 -07006873 MAC2STR(wpa_auth_get_spa(sm)), vlan_id);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006874
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07006875 wpa_group_get(sm->wpa_auth, group);
6876 wpa_group_put(sm->wpa_auth, sm->group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006877 sm->group = group;
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07006878
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006879 return 0;
6880}
6881
6882
6883void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth,
6884 struct wpa_state_machine *sm, int ack)
6885{
Hai Shalomfdcde762020-04-02 11:19:20 -07006886 if (!wpa_auth || !sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006887 return;
6888 wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key TX status for STA " MACSTR
Sunil Raviaf8751c2023-03-29 11:35:17 -07006889 " ack=%d", MAC2STR(wpa_auth_get_spa(sm)), ack);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006890 if (sm->pending_1_of_4_timeout && ack) {
6891 /*
6892 * Some deployed supplicant implementations update their SNonce
6893 * for each EAPOL-Key 2/4 message even within the same 4-way
6894 * handshake and then fail to use the first SNonce when
6895 * deriving the PTK. This results in unsuccessful 4-way
6896 * handshake whenever the relatively short initial timeout is
6897 * reached and EAPOL-Key 1/4 is retransmitted. Try to work
6898 * around this by increasing the timeout now that we know that
6899 * the station has received the frame.
6900 */
6901 int timeout_ms = eapol_key_timeout_subseq;
Hai Shalomfdcde762020-04-02 11:19:20 -07006902 wpa_printf(MSG_DEBUG,
6903 "WPA: Increase initial EAPOL-Key 1/4 timeout by %u ms because of acknowledged frame",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006904 timeout_ms);
6905 eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm);
6906 eloop_register_timeout(timeout_ms / 1000,
6907 (timeout_ms % 1000) * 1000,
6908 wpa_send_eapol_timeout, wpa_auth, sm);
6909 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006910
6911#ifdef CONFIG_TESTING_OPTIONS
6912 if (sm->eapol_status_cb) {
6913 sm->eapol_status_cb(sm->eapol_status_cb_ctx1,
6914 sm->eapol_status_cb_ctx2);
6915 sm->eapol_status_cb = NULL;
6916 }
6917#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006918}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006919
6920
6921int wpa_auth_uses_sae(struct wpa_state_machine *sm)
6922{
Hai Shalomfdcde762020-04-02 11:19:20 -07006923 if (!sm)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006924 return 0;
6925 return wpa_key_mgmt_sae(sm->wpa_key_mgmt);
6926}
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006927
6928
6929int wpa_auth_uses_ft_sae(struct wpa_state_machine *sm)
6930{
Hai Shalomfdcde762020-04-02 11:19:20 -07006931 if (!sm)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006932 return 0;
Sunil Ravi89eba102022-09-13 21:04:37 -07006933 return sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_SAE ||
6934 sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_SAE_EXT_KEY;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006935}
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08006936
6937
6938#ifdef CONFIG_P2P
6939int wpa_auth_get_ip_addr(struct wpa_state_machine *sm, u8 *addr)
6940{
Hai Shalomfdcde762020-04-02 11:19:20 -07006941 if (!sm || WPA_GET_BE32(sm->ip_addr) == 0)
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08006942 return -1;
6943 os_memcpy(addr, sm->ip_addr, 4);
6944 return 0;
6945}
6946#endif /* CONFIG_P2P */
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08006947
6948
6949int wpa_auth_radius_das_disconnect_pmksa(struct wpa_authenticator *wpa_auth,
6950 struct radius_das_attrs *attr)
6951{
6952 return pmksa_cache_auth_radius_das_disconnect(wpa_auth->pmksa, attr);
6953}
Dmitry Shmidt7f656022015-02-25 14:36:37 -08006954
6955
6956void wpa_auth_reconfig_group_keys(struct wpa_authenticator *wpa_auth)
6957{
6958 struct wpa_group *group;
6959
6960 if (!wpa_auth)
6961 return;
6962 for (group = wpa_auth->group; group; group = group->next)
6963 wpa_group_config_group_keys(wpa_auth, group);
6964}
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006965
6966
6967#ifdef CONFIG_FILS
6968
6969struct wpa_auth_fils_iter_data {
6970 struct wpa_authenticator *auth;
6971 const u8 *cache_id;
6972 struct rsn_pmksa_cache_entry *pmksa;
6973 const u8 *spa;
6974 const u8 *pmkid;
6975};
6976
6977
6978static int wpa_auth_fils_iter(struct wpa_authenticator *a, void *ctx)
6979{
6980 struct wpa_auth_fils_iter_data *data = ctx;
6981
6982 if (a == data->auth || !a->conf.fils_cache_id_set ||
6983 os_memcmp(a->conf.fils_cache_id, data->cache_id,
6984 FILS_CACHE_ID_LEN) != 0)
6985 return 0;
6986 data->pmksa = pmksa_cache_auth_get(a->pmksa, data->spa, data->pmkid);
6987 return data->pmksa != NULL;
6988}
6989
6990
6991struct rsn_pmksa_cache_entry *
6992wpa_auth_pmksa_get_fils_cache_id(struct wpa_authenticator *wpa_auth,
6993 const u8 *sta_addr, const u8 *pmkid)
6994{
6995 struct wpa_auth_fils_iter_data idata;
6996
6997 if (!wpa_auth->conf.fils_cache_id_set)
6998 return NULL;
6999 idata.auth = wpa_auth;
7000 idata.cache_id = wpa_auth->conf.fils_cache_id;
7001 idata.pmksa = NULL;
7002 idata.spa = sta_addr;
7003 idata.pmkid = pmkid;
7004 wpa_auth_for_each_auth(wpa_auth, wpa_auth_fils_iter, &idata);
7005 return idata.pmksa;
7006}
7007
7008
7009#ifdef CONFIG_IEEE80211R_AP
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00007010int wpa_auth_write_fte(struct wpa_authenticator *wpa_auth,
7011 struct wpa_state_machine *sm,
Roshan Pius3a1667e2018-07-03 15:17:14 -07007012 u8 *buf, size_t len)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007013{
7014 struct wpa_auth_config *conf = &wpa_auth->conf;
7015
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00007016 return wpa_write_ftie(conf, sm->wpa_key_mgmt, sm->xxkey_len,
7017 conf->r0_key_holder, conf->r0_key_holder_len,
Hai Shalomfdcde762020-04-02 11:19:20 -07007018 NULL, NULL, buf, len, NULL, 0, 0);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007019}
7020#endif /* CONFIG_IEEE80211R_AP */
7021
7022
7023void wpa_auth_get_fils_aead_params(struct wpa_state_machine *sm,
7024 u8 *fils_anonce, u8 *fils_snonce,
7025 u8 *fils_kek, size_t *fils_kek_len)
7026{
7027 os_memcpy(fils_anonce, sm->ANonce, WPA_NONCE_LEN);
7028 os_memcpy(fils_snonce, sm->SNonce, WPA_NONCE_LEN);
7029 os_memcpy(fils_kek, sm->PTK.kek, WPA_KEK_MAX_LEN);
7030 *fils_kek_len = sm->PTK.kek_len;
7031}
7032
Hai Shalom81f62d82019-07-22 12:10:00 -07007033
7034void wpa_auth_add_fils_pmk_pmkid(struct wpa_state_machine *sm, const u8 *pmk,
7035 size_t pmk_len, const u8 *pmkid)
7036{
7037 os_memcpy(sm->PMK, pmk, pmk_len);
7038 sm->pmk_len = pmk_len;
7039 os_memcpy(sm->pmkid, pmkid, PMKID_LEN);
7040 sm->pmkid_set = 1;
7041}
7042
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007043#endif /* CONFIG_FILS */
7044
7045
Hai Shalom021b0b52019-04-10 11:17:58 -07007046void wpa_auth_set_auth_alg(struct wpa_state_machine *sm, u16 auth_alg)
7047{
7048 if (sm)
7049 sm->auth_alg = auth_alg;
7050}
7051
7052
Sunil Ravic0f5d412024-09-11 22:12:49 +00007053void wpa_auth_set_rsn_selection(struct wpa_state_machine *sm, const u8 *ie,
7054 size_t len)
Sunil Ravi7f769292024-07-23 22:21:32 +00007055{
Sunil Ravic0f5d412024-09-11 22:12:49 +00007056 if (!sm)
7057 return;
7058 os_free(sm->rsn_selection);
7059 sm->rsn_selection = NULL;
7060 sm->rsn_selection_len = 0;
7061 sm->rsn_override = false;
7062 sm->rsn_override_2 = false;
7063 if (ie) {
7064 if (len >= 1) {
7065 if (ie[0] == RSN_SELECTION_RSNE_OVERRIDE)
7066 sm->rsn_override = true;
7067 else if (ie[0] == RSN_SELECTION_RSNE_OVERRIDE_2)
7068 sm->rsn_override_2 = true;
7069 }
7070 sm->rsn_selection = os_memdup(ie, len);
7071 if (sm->rsn_selection)
7072 sm->rsn_selection_len = len;
7073 }
Sunil Ravi7f769292024-07-23 22:21:32 +00007074}
7075
7076
Hai Shalom021b0b52019-04-10 11:17:58 -07007077#ifdef CONFIG_DPP2
7078void wpa_auth_set_dpp_z(struct wpa_state_machine *sm, const struct wpabuf *z)
7079{
7080 if (sm) {
7081 wpabuf_clear_free(sm->dpp_z);
7082 sm->dpp_z = z ? wpabuf_dup(z) : NULL;
7083 }
7084}
7085#endif /* CONFIG_DPP2 */
7086
7087
Sunil Ravi7f769292024-07-23 22:21:32 +00007088void wpa_auth_set_ssid_protection(struct wpa_state_machine *sm, bool val)
7089{
7090 if (sm)
7091 sm->ssid_protection = val;
7092}
7093
7094
Hai Shalom899fcc72020-10-19 14:38:18 -07007095void wpa_auth_set_transition_disable(struct wpa_authenticator *wpa_auth,
7096 u8 val)
7097{
7098 if (wpa_auth)
7099 wpa_auth->conf.transition_disable = val;
7100}
7101
7102
Roshan Pius3a1667e2018-07-03 15:17:14 -07007103#ifdef CONFIG_TESTING_OPTIONS
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007104
7105int wpa_auth_resend_m1(struct wpa_state_machine *sm, int change_anonce,
7106 void (*cb)(void *ctx1, void *ctx2),
7107 void *ctx1, void *ctx2)
7108{
7109 const u8 *anonce = sm->ANonce;
7110 u8 anonce_buf[WPA_NONCE_LEN];
7111
7112 if (change_anonce) {
7113 if (random_get_bytes(anonce_buf, WPA_NONCE_LEN))
7114 return -1;
7115 anonce = anonce_buf;
7116 }
7117
Sunil Raviaf8751c2023-03-29 11:35:17 -07007118 wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007119 "sending 1/4 msg of 4-Way Handshake (TESTING)");
7120 wpa_send_eapol(sm->wpa_auth, sm,
7121 WPA_KEY_INFO_ACK | WPA_KEY_INFO_KEY_TYPE, NULL,
7122 anonce, NULL, 0, 0, 0);
7123 return 0;
7124}
7125
7126
7127int wpa_auth_resend_m3(struct wpa_state_machine *sm,
7128 void (*cb)(void *ctx1, void *ctx2),
7129 void *ctx1, void *ctx2)
7130{
Roshan Pius3a1667e2018-07-03 15:17:14 -07007131 u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde, *pos;
Roshan Pius3a1667e2018-07-03 15:17:14 -07007132 u8 *opos;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007133 size_t gtk_len, kde_len;
Hai Shalom899fcc72020-10-19 14:38:18 -07007134 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007135 struct wpa_group *gsm = sm->group;
7136 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07007137 int wpa_ie_len, secure, gtkidx, encr = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07007138 u8 hdr[2];
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007139
7140 /* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, [MDIE],
Hai Shalomfdcde762020-04-02 11:19:20 -07007141 GTK[GN], IGTK, [BIGTK], [FTIE], [TIE * 2])
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007142 */
7143
7144 /* Use 0 RSC */
7145 os_memset(rsc, 0, WPA_KEY_RSC_LEN);
7146 /* If FT is used, wpa_auth->wpa_ie includes both RSNIE and MDIE */
7147 wpa_ie = sm->wpa_auth->wpa_ie;
7148 wpa_ie_len = sm->wpa_auth->wpa_ie_len;
7149 if (sm->wpa == WPA_VERSION_WPA &&
7150 (sm->wpa_auth->conf.wpa & WPA_PROTO_RSN) &&
7151 wpa_ie_len > wpa_ie[1] + 2 && wpa_ie[0] == WLAN_EID_RSN) {
7152 /* WPA-only STA, remove RSN IE and possible MDIE */
7153 wpa_ie = wpa_ie + wpa_ie[1] + 2;
Hai Shalom60840252021-02-19 19:02:11 -08007154 if (wpa_ie[0] == WLAN_EID_RSNX)
7155 wpa_ie = wpa_ie + wpa_ie[1] + 2;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007156 if (wpa_ie[0] == WLAN_EID_MOBILITY_DOMAIN)
7157 wpa_ie = wpa_ie + wpa_ie[1] + 2;
7158 wpa_ie_len = wpa_ie[1] + 2;
7159 }
Sunil Raviaf8751c2023-03-29 11:35:17 -07007160 wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007161 "sending 3/4 msg of 4-Way Handshake (TESTING)");
7162 if (sm->wpa == WPA_VERSION_WPA2) {
7163 /* WPA2 send GTK in the 4-way handshake */
7164 secure = 1;
7165 gtk = gsm->GTK[gsm->GN - 1];
7166 gtk_len = gsm->GTK_len;
Hai Shalomc3565922019-10-28 11:58:20 -07007167 gtkidx = gsm->GN;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007168 _rsc = rsc;
7169 encr = 1;
7170 } else {
7171 /* WPA does not include GTK in msg 3/4 */
7172 secure = 0;
7173 gtk = NULL;
7174 gtk_len = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007175 _rsc = NULL;
7176 if (sm->rx_eapol_key_secure) {
7177 /*
7178 * It looks like Windows 7 supplicant tries to use
7179 * Secure bit in msg 2/4 after having reported Michael
7180 * MIC failure and it then rejects the 4-way handshake
7181 * if msg 3/4 does not set Secure bit. Work around this
7182 * by setting the Secure bit here even in the case of
7183 * WPA if the supplicant used it first.
7184 */
Sunil Raviaf8751c2023-03-29 11:35:17 -07007185 wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm),
7186 LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07007187 "STA used Secure bit in WPA msg 2/4 - set Secure for 3/4 as workaround");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007188 secure = 1;
7189 }
7190 }
7191
Hai Shalom74f70d42019-02-11 14:42:39 -08007192 kde_len = wpa_ie_len + ieee80211w_kde_len(sm) + ocv_oci_len(sm);
Hai Shalomfdcde762020-04-02 11:19:20 -07007193
7194 if (sm->use_ext_key_id)
7195 kde_len += 2 + RSN_SELECTOR_LEN + 2;
7196
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007197 if (gtk)
7198 kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len;
7199#ifdef CONFIG_IEEE80211R_AP
7200 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
7201 kde_len += 2 + PMKID_LEN; /* PMKR1Name into RSN IE */
7202 kde_len += 300; /* FTIE + 2 * TIE */
7203 }
7204#endif /* CONFIG_IEEE80211R_AP */
7205 kde = os_malloc(kde_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07007206 if (!kde)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007207 return -1;
7208
7209 pos = kde;
7210 os_memcpy(pos, wpa_ie, wpa_ie_len);
7211 pos += wpa_ie_len;
7212#ifdef CONFIG_IEEE80211R_AP
7213 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
7214 int res;
7215 size_t elen;
7216
7217 elen = pos - kde;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00007218 res = wpa_insert_pmkid(kde, &elen, sm->pmk_r1_name, true);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007219 if (res < 0) {
Hai Shalomfdcde762020-04-02 11:19:20 -07007220 wpa_printf(MSG_ERROR,
7221 "FT: Failed to insert PMKR1Name into RSN IE in EAPOL-Key data");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007222 os_free(kde);
7223 return -1;
7224 }
7225 pos -= wpa_ie_len;
7226 pos += elen;
7227 }
7228#endif /* CONFIG_IEEE80211R_AP */
Hai Shalomfdcde762020-04-02 11:19:20 -07007229 hdr[1] = 0;
7230
7231 if (sm->use_ext_key_id) {
7232 hdr[0] = sm->keyidx_active & 0x01;
7233 pos = wpa_add_kde(pos, RSN_KEY_DATA_KEYID, hdr, 2, NULL, 0);
7234 }
7235
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007236 if (gtk) {
Hai Shalomc3565922019-10-28 11:58:20 -07007237 hdr[0] = gtkidx & 0x03;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007238 pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
7239 gtk, gtk_len);
7240 }
7241 opos = pos;
7242 pos = ieee80211w_kde_add(sm, pos);
Roshan Pius3a1667e2018-07-03 15:17:14 -07007243 if (pos - opos >= 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN) {
7244 /* skip KDE header and keyid */
7245 opos += 2 + RSN_SELECTOR_LEN + 2;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007246 os_memset(opos, 0, 6); /* clear PN */
7247 }
Hai Shalom899fcc72020-10-19 14:38:18 -07007248 if (ocv_oci_add(sm, &pos, conf->oci_freq_override_eapol_m3) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -08007249 os_free(kde);
7250 return -1;
7251 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007252
7253#ifdef CONFIG_IEEE80211R_AP
7254 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
7255 int res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007256
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007257 if (sm->assoc_resp_ftie &&
7258 kde + kde_len - pos >= 2 + sm->assoc_resp_ftie[1]) {
7259 os_memcpy(pos, sm->assoc_resp_ftie,
7260 2 + sm->assoc_resp_ftie[1]);
7261 res = 2 + sm->assoc_resp_ftie[1];
7262 } else {
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00007263 res = wpa_write_ftie(conf, sm->wpa_key_mgmt,
7264 sm->xxkey_len,
Roshan Pius3a1667e2018-07-03 15:17:14 -07007265 conf->r0_key_holder,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007266 conf->r0_key_holder_len,
7267 NULL, NULL, pos,
7268 kde + kde_len - pos,
Hai Shalomfdcde762020-04-02 11:19:20 -07007269 NULL, 0, 0);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007270 }
7271 if (res < 0) {
Hai Shalomfdcde762020-04-02 11:19:20 -07007272 wpa_printf(MSG_ERROR,
7273 "FT: Failed to insert FTIE into EAPOL-Key Key Data");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007274 os_free(kde);
7275 return -1;
7276 }
7277 pos += res;
7278
7279 /* TIE[ReassociationDeadline] (TU) */
7280 *pos++ = WLAN_EID_TIMEOUT_INTERVAL;
7281 *pos++ = 5;
7282 *pos++ = WLAN_TIMEOUT_REASSOC_DEADLINE;
7283 WPA_PUT_LE32(pos, conf->reassociation_deadline);
7284 pos += 4;
7285
7286 /* TIE[KeyLifetime] (seconds) */
7287 *pos++ = WLAN_EID_TIMEOUT_INTERVAL;
7288 *pos++ = 5;
7289 *pos++ = WLAN_TIMEOUT_KEY_LIFETIME;
Roshan Pius3a1667e2018-07-03 15:17:14 -07007290 WPA_PUT_LE32(pos, conf->r0_key_lifetime);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007291 pos += 4;
7292 }
7293#endif /* CONFIG_IEEE80211R_AP */
7294
7295 wpa_send_eapol(sm->wpa_auth, sm,
7296 (secure ? WPA_KEY_INFO_SECURE : 0) |
7297 (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
7298 WPA_KEY_INFO_MIC : 0) |
7299 WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL |
7300 WPA_KEY_INFO_KEY_TYPE,
Hai Shalomc3565922019-10-28 11:58:20 -07007301 _rsc, sm->ANonce, kde, pos - kde, 0, encr);
Sunil Ravia04bd252022-05-02 22:54:18 -07007302 bin_clear_free(kde, kde_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007303 return 0;
7304}
7305
7306
7307int wpa_auth_resend_group_m1(struct wpa_state_machine *sm,
7308 void (*cb)(void *ctx1, void *ctx2),
7309 void *ctx1, void *ctx2)
7310{
7311 u8 rsc[WPA_KEY_RSC_LEN];
Hai Shalom899fcc72020-10-19 14:38:18 -07007312 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007313 struct wpa_group *gsm = sm->group;
7314 const u8 *kde;
Roshan Pius3a1667e2018-07-03 15:17:14 -07007315 u8 *kde_buf = NULL, *pos, hdr[2];
Roshan Pius3a1667e2018-07-03 15:17:14 -07007316 u8 *opos;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007317 size_t kde_len;
7318 u8 *gtk;
7319
7320 /* Send EAPOL(1, 1, 1, !Pair, G, RSC, GNonce, MIC(PTK), GTK[GN]) */
7321 os_memset(rsc, 0, WPA_KEY_RSC_LEN);
7322 /* Use 0 RSC */
Sunil Raviaf8751c2023-03-29 11:35:17 -07007323 wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007324 "sending 1/2 msg of Group Key Handshake (TESTING)");
7325
7326 gtk = gsm->GTK[gsm->GN - 1];
7327 if (sm->wpa == WPA_VERSION_WPA2) {
7328 kde_len = 2 + RSN_SELECTOR_LEN + 2 + gsm->GTK_len +
Hai Shalom74f70d42019-02-11 14:42:39 -08007329 ieee80211w_kde_len(sm) + ocv_oci_len(sm);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007330 kde_buf = os_malloc(kde_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07007331 if (!kde_buf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007332 return -1;
7333
7334 kde = pos = kde_buf;
7335 hdr[0] = gsm->GN & 0x03;
7336 hdr[1] = 0;
7337 pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
7338 gtk, gsm->GTK_len);
7339 opos = pos;
7340 pos = ieee80211w_kde_add(sm, pos);
Roshan Pius3a1667e2018-07-03 15:17:14 -07007341 if (pos - opos >=
7342 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN) {
7343 /* skip KDE header and keyid */
7344 opos += 2 + RSN_SELECTOR_LEN + 2;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007345 os_memset(opos, 0, 6); /* clear PN */
7346 }
Hai Shalom899fcc72020-10-19 14:38:18 -07007347 if (ocv_oci_add(sm, &pos,
7348 conf->oci_freq_override_eapol_g1) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -08007349 os_free(kde_buf);
7350 return -1;
7351 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007352 kde_len = pos - kde;
7353 } else {
7354 kde = gtk;
7355 kde_len = gsm->GTK_len;
7356 }
7357
7358 sm->eapol_status_cb = cb;
7359 sm->eapol_status_cb_ctx1 = ctx1;
7360 sm->eapol_status_cb_ctx2 = ctx2;
7361
7362 wpa_send_eapol(sm->wpa_auth, sm,
7363 WPA_KEY_INFO_SECURE |
7364 (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
7365 WPA_KEY_INFO_MIC : 0) |
7366 WPA_KEY_INFO_ACK |
7367 (!sm->Pair ? WPA_KEY_INFO_INSTALL : 0),
7368 rsc, NULL, kde, kde_len, gsm->GN, 1);
7369
Sunil Ravia04bd252022-05-02 22:54:18 -07007370 bin_clear_free(kde_buf, kde_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007371 return 0;
7372}
7373
Roshan Pius3a1667e2018-07-03 15:17:14 -07007374
7375int wpa_auth_rekey_gtk(struct wpa_authenticator *wpa_auth)
7376{
7377 if (!wpa_auth)
7378 return -1;
Sunil Ravi7f769292024-07-23 22:21:32 +00007379 eloop_cancel_timeout(wpa_rekey_gtk,
7380 wpa_get_primary_auth(wpa_auth), NULL);
7381 return eloop_register_timeout(0, 0, wpa_rekey_gtk,
7382 wpa_get_primary_auth(wpa_auth), NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07007383}
7384
Hai Shalomb755a2a2020-04-23 21:49:02 -07007385
Hai Shaloma20dcd72022-02-04 13:43:00 -08007386int wpa_auth_rekey_ptk(struct wpa_authenticator *wpa_auth,
7387 struct wpa_state_machine *sm)
7388{
7389 if (!wpa_auth || !sm)
7390 return -1;
7391 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "rekeying PTK");
7392 wpa_request_new_ptk(sm);
7393 wpa_sm_step(sm);
7394 return 0;
7395}
7396
7397
Hai Shalomb755a2a2020-04-23 21:49:02 -07007398void wpa_auth_set_ft_rsnxe_used(struct wpa_authenticator *wpa_auth, int val)
7399{
7400 if (wpa_auth)
7401 wpa_auth->conf.ft_rsnxe_used = val;
7402}
7403
Hai Shalom899fcc72020-10-19 14:38:18 -07007404
7405void wpa_auth_set_ocv_override_freq(struct wpa_authenticator *wpa_auth,
7406 enum wpa_auth_ocv_override_frame frame,
7407 unsigned int freq)
7408{
7409 if (!wpa_auth)
7410 return;
7411 switch (frame) {
7412 case WPA_AUTH_OCV_OVERRIDE_EAPOL_M3:
7413 wpa_auth->conf.oci_freq_override_eapol_m3 = freq;
7414 break;
7415 case WPA_AUTH_OCV_OVERRIDE_EAPOL_G1:
7416 wpa_auth->conf.oci_freq_override_eapol_g1 = freq;
7417 break;
7418 case WPA_AUTH_OCV_OVERRIDE_FT_ASSOC:
7419 wpa_auth->conf.oci_freq_override_ft_assoc = freq;
7420 break;
7421 case WPA_AUTH_OCV_OVERRIDE_FILS_ASSOC:
7422 wpa_auth->conf.oci_freq_override_fils_assoc = freq;
7423 break;
7424 }
7425}
7426
Kai Shie75b0652020-11-24 20:31:29 -08007427void wpa_auth_set_skip_send_eapol(struct wpa_authenticator *wpa_auth,
7428 u8 val)
7429{
7430 if (wpa_auth)
7431 wpa_auth->conf.skip_send_eapol = val;
7432}
7433
7434void wpa_auth_set_enable_eapol_large_timeout(struct wpa_authenticator *wpa_auth,
7435 u8 val)
7436{
7437 if (wpa_auth)
7438 wpa_auth->conf.enable_eapol_large_timeout = val;
7439}
7440
7441
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007442#endif /* CONFIG_TESTING_OPTIONS */
Sunil Ravia04bd252022-05-02 22:54:18 -07007443
7444
7445void wpa_auth_sta_radius_psk_resp(struct wpa_state_machine *sm, bool success)
7446{
7447 if (!sm->waiting_radius_psk) {
7448 wpa_printf(MSG_DEBUG,
7449 "Ignore RADIUS PSK response for " MACSTR
7450 " that did not wait one",
7451 MAC2STR(sm->addr));
7452 return;
7453 }
7454
7455 wpa_printf(MSG_DEBUG, "RADIUS PSK response for " MACSTR " (%s)",
7456 MAC2STR(sm->addr), success ? "success" : "fail");
7457 sm->waiting_radius_psk = 0;
7458
7459 if (success) {
7460 /* Try to process the EAPOL-Key msg 2/4 again */
7461 sm->EAPOLKeyReceived = true;
7462 } else {
7463 sm->Disconnect = true;
7464 }
7465
7466 eloop_register_timeout(0, 0, wpa_sm_call_step, sm, NULL);
7467}
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007468
7469
Sunil Ravi7f769292024-07-23 22:21:32 +00007470void wpa_auth_set_ml_info(struct wpa_state_machine *sm,
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007471 u8 mld_assoc_link_id, struct mld_info *info)
7472{
7473#ifdef CONFIG_IEEE80211BE
Sunil Ravi7f769292024-07-23 22:21:32 +00007474 unsigned int link_id;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007475
7476 if (!info)
7477 return;
7478
7479 os_memset(sm->mld_links, 0, sizeof(sm->mld_links));
Sunil Ravi7f769292024-07-23 22:21:32 +00007480 sm->n_mld_affiliated_links = 0;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007481
7482 wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
7483 "MLD: Initialization");
7484
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007485 os_memcpy(sm->peer_mld_addr, info->common_info.mld_addr, ETH_ALEN);
7486
7487 sm->mld_assoc_link_id = mld_assoc_link_id;
7488
Sunil Ravi7f769292024-07-23 22:21:32 +00007489 for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007490 struct mld_link_info *link = &info->links[link_id];
7491 struct mld_link *sm_link = &sm->mld_links[link_id];
Sunil Ravi7f769292024-07-23 22:21:32 +00007492 struct wpa_get_link_auth_ctx ctx;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007493
7494 sm_link->valid = link->valid;
7495 if (!link->valid)
7496 continue;
7497
7498 os_memcpy(sm_link->peer_addr, link->peer_addr, ETH_ALEN);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007499
7500 wpa_printf(MSG_DEBUG,
Sunil Ravi7f769292024-07-23 22:21:32 +00007501 "WPA_AUTH: MLD: id=%u, peer=" MACSTR,
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007502 link_id,
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007503 MAC2STR(sm_link->peer_addr));
7504
Sunil Ravi7f769292024-07-23 22:21:32 +00007505 if (link_id != mld_assoc_link_id) {
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007506 sm->n_mld_affiliated_links++;
Sunil Ravi7f769292024-07-23 22:21:32 +00007507 ctx.addr = link->local_addr;
7508 ctx.mld_addr = NULL;
7509 ctx.link_id = -1;
7510 ctx.wpa_auth = NULL;
7511 wpa_auth_for_each_auth(sm->wpa_auth,
7512 wpa_get_link_sta_auth, &ctx);
Sunil Ravi79e6c4f2025-01-04 00:47:06 +00007513 if (ctx.wpa_auth)
Sunil Ravi7f769292024-07-23 22:21:32 +00007514 sm_link->wpa_auth = ctx.wpa_auth;
Sunil Ravi7f769292024-07-23 22:21:32 +00007515 } else {
7516 sm_link->wpa_auth = sm->wpa_auth;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007517 }
7518
Sunil Ravi7f769292024-07-23 22:21:32 +00007519 if (!sm_link->wpa_auth)
7520 wpa_printf(MSG_ERROR,
7521 "Unable to find authenticator object for ML STA "
7522 MACSTR " on link id %d",
7523 MAC2STR(sm->wpa_auth->mld_addr),
7524 link_id);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007525 }
7526#endif /* CONFIG_IEEE80211BE */
7527}