blob: 3af3404a34bf9ddef3114ae0ca8dc755ceba2956 [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) {
136 if (link_id == release_link_id) {
137 wpa_group_put(sm->mld_links[link_id].wpa_auth,
138 sm->mld_links[link_id].wpa_auth->group);
139 sm->mld_links[link_id].wpa_auth = NULL;
140 }
141 }
142}
143
144
145struct wpa_get_link_auth_ctx {
146 const u8 *addr;
147 const u8 *mld_addr;
148 int link_id;
149 struct wpa_authenticator *wpa_auth;
150};
151
152static int wpa_get_link_sta_auth(struct wpa_authenticator *wpa_auth, void *data)
153{
154 struct wpa_get_link_auth_ctx *ctx = data;
155
156 if (!wpa_auth->is_ml)
157 return 0;
158
159 if (ctx->mld_addr &&
160 !ether_addr_equal(wpa_auth->mld_addr, ctx->mld_addr))
161 return 0;
162
163 if ((ctx->addr && ether_addr_equal(wpa_auth->addr, ctx->addr)) ||
164 (ctx->link_id > -1 && wpa_auth->is_ml &&
165 wpa_auth->link_id == ctx->link_id)) {
166 ctx->wpa_auth = wpa_auth;
167 return 1;
168
169 }
170 return 0;
171}
172
173
174static struct wpa_authenticator *
175wpa_get_link_auth(struct wpa_authenticator *wpa_auth, int link_id)
176{
177 struct wpa_get_link_auth_ctx ctx;
178
179 ctx.addr = NULL;
180 ctx.mld_addr = wpa_auth->mld_addr;
181 ctx.link_id = link_id;
182 ctx.wpa_auth = NULL;
183 wpa_auth_for_each_auth(wpa_auth, wpa_get_link_sta_auth, &ctx);
184 return ctx.wpa_auth;
185}
186
187
188static int wpa_get_primary_auth_cb(struct wpa_authenticator *wpa_auth,
189 void *data)
190{
191 struct wpa_get_link_auth_ctx *ctx = data;
192
193 if (!wpa_auth->is_ml ||
194 !ether_addr_equal(wpa_auth->mld_addr, ctx->addr) ||
195 !wpa_auth->primary_auth)
196 return 0;
197
198 ctx->wpa_auth = wpa_auth;
199 return 1;
200}
201
202#endif /* CONFIG_IEEE80211BE */
203
204
205static struct wpa_authenticator *
206wpa_get_primary_auth(struct wpa_authenticator *wpa_auth)
207{
208#ifdef CONFIG_IEEE80211BE
209 struct wpa_get_link_auth_ctx ctx;
210
211 if (!wpa_auth || !wpa_auth->is_ml || wpa_auth->primary_auth)
212 return wpa_auth;
213
214 ctx.addr = wpa_auth->mld_addr;
215 ctx.wpa_auth = NULL;
216 wpa_auth_for_each_auth(wpa_auth, wpa_get_primary_auth_cb, &ctx);
217
218 return ctx.wpa_auth;
219#else /* CONFIG_IEEE80211BE */
220 return wpa_auth;
221#endif /* CONFIG_IEEE80211BE */
222}
223
224
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800225static inline int wpa_auth_mic_failure_report(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700226 struct wpa_authenticator *wpa_auth, const u8 *addr)
227{
Paul Stewart092955c2017-02-06 09:13:09 -0800228 if (wpa_auth->cb->mic_failure_report)
229 return wpa_auth->cb->mic_failure_report(wpa_auth->cb_ctx, addr);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800230 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700231}
232
233
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700234static inline void wpa_auth_psk_failure_report(
235 struct wpa_authenticator *wpa_auth, const u8 *addr)
236{
Paul Stewart092955c2017-02-06 09:13:09 -0800237 if (wpa_auth->cb->psk_failure_report)
238 wpa_auth->cb->psk_failure_report(wpa_auth->cb_ctx, addr);
Dmitry Shmidtdda10c22015-03-24 16:05:01 -0700239}
240
241
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700242static inline void wpa_auth_set_eapol(struct wpa_authenticator *wpa_auth,
243 const u8 *addr, wpa_eapol_variable var,
244 int value)
245{
Paul Stewart092955c2017-02-06 09:13:09 -0800246 if (wpa_auth->cb->set_eapol)
247 wpa_auth->cb->set_eapol(wpa_auth->cb_ctx, addr, var, value);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700248}
249
250
251static inline int wpa_auth_get_eapol(struct wpa_authenticator *wpa_auth,
252 const u8 *addr, wpa_eapol_variable var)
253{
Hai Shalomfdcde762020-04-02 11:19:20 -0700254 if (!wpa_auth->cb->get_eapol)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700255 return -1;
Paul Stewart092955c2017-02-06 09:13:09 -0800256 return wpa_auth->cb->get_eapol(wpa_auth->cb_ctx, addr, var);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700257}
258
259
260static inline const u8 * wpa_auth_get_psk(struct wpa_authenticator *wpa_auth,
Dmitry Shmidt391c59f2013-09-03 12:16:28 -0700261 const u8 *addr,
262 const u8 *p2p_dev_addr,
Hai Shalom021b0b52019-04-10 11:17:58 -0700263 const u8 *prev_psk, size_t *psk_len,
264 int *vlan_id)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700265{
Hai Shalomfdcde762020-04-02 11:19:20 -0700266 if (!wpa_auth->cb->get_psk)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700267 return NULL;
Paul Stewart092955c2017-02-06 09:13:09 -0800268 return wpa_auth->cb->get_psk(wpa_auth->cb_ctx, addr, p2p_dev_addr,
Hai Shalom021b0b52019-04-10 11:17:58 -0700269 prev_psk, psk_len, vlan_id);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700270}
271
272
273static inline int wpa_auth_get_msk(struct wpa_authenticator *wpa_auth,
274 const u8 *addr, u8 *msk, size_t *len)
275{
Hai Shalomfdcde762020-04-02 11:19:20 -0700276 if (!wpa_auth->cb->get_msk)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700277 return -1;
Paul Stewart092955c2017-02-06 09:13:09 -0800278 return wpa_auth->cb->get_msk(wpa_auth->cb_ctx, addr, msk, len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700279}
280
281
282static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth,
283 int vlan_id,
284 enum wpa_alg alg, const u8 *addr, int idx,
Hai Shalomfdcde762020-04-02 11:19:20 -0700285 u8 *key, size_t key_len,
286 enum key_flag key_flag)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700287{
Hai Shalomfdcde762020-04-02 11:19:20 -0700288 if (!wpa_auth->cb->set_key)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700289 return -1;
Paul Stewart092955c2017-02-06 09:13:09 -0800290 return wpa_auth->cb->set_key(wpa_auth->cb_ctx, vlan_id, alg, addr, idx,
Hai Shalomfdcde762020-04-02 11:19:20 -0700291 key, key_len, key_flag);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700292}
293
294
Sunil Ravi89eba102022-09-13 21:04:37 -0700295#ifdef CONFIG_PASN
296static inline int wpa_auth_set_ltf_keyseed(struct wpa_authenticator *wpa_auth,
297 const u8 *peer_addr,
298 const u8 *ltf_keyseed,
299 size_t ltf_keyseed_len)
300{
301 if (!wpa_auth->cb->set_ltf_keyseed)
302 return -1;
303 return wpa_auth->cb->set_ltf_keyseed(wpa_auth->cb_ctx, peer_addr,
304 ltf_keyseed, ltf_keyseed_len);
305}
306#endif /* CONFIG_PASN */
307
308
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700309static inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth,
310 const u8 *addr, int idx, u8 *seq)
311{
Hai Shalomfdcde762020-04-02 11:19:20 -0700312 int res;
313
314 if (!wpa_auth->cb->get_seqnum)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700315 return -1;
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000316#ifdef CONFIG_TESTING_OPTIONS
317 os_memset(seq, 0, WPA_KEY_RSC_LEN);
318#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomfdcde762020-04-02 11:19:20 -0700319 res = wpa_auth->cb->get_seqnum(wpa_auth->cb_ctx, addr, idx, seq);
320#ifdef CONFIG_TESTING_OPTIONS
321 if (!addr && idx < 4 && wpa_auth->conf.gtk_rsc_override_set) {
322 wpa_printf(MSG_DEBUG,
323 "TESTING: Override GTK RSC %016llx --> %016llx",
324 (long long unsigned) WPA_GET_LE64(seq),
325 (long long unsigned)
326 WPA_GET_LE64(wpa_auth->conf.gtk_rsc_override));
327 os_memcpy(seq, wpa_auth->conf.gtk_rsc_override,
328 WPA_KEY_RSC_LEN);
329 }
330 if (!addr && idx >= 4 && idx <= 5 &&
331 wpa_auth->conf.igtk_rsc_override_set) {
332 wpa_printf(MSG_DEBUG,
333 "TESTING: Override IGTK RSC %016llx --> %016llx",
334 (long long unsigned) WPA_GET_LE64(seq),
335 (long long unsigned)
336 WPA_GET_LE64(wpa_auth->conf.igtk_rsc_override));
337 os_memcpy(seq, wpa_auth->conf.igtk_rsc_override,
338 WPA_KEY_RSC_LEN);
339 }
340#endif /* CONFIG_TESTING_OPTIONS */
341 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700342}
343
344
345static inline int
346wpa_auth_send_eapol(struct wpa_authenticator *wpa_auth, const u8 *addr,
347 const u8 *data, size_t data_len, int encrypt)
348{
Hai Shalomfdcde762020-04-02 11:19:20 -0700349 if (!wpa_auth->cb->send_eapol)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700350 return -1;
Kai Shie75b0652020-11-24 20:31:29 -0800351#ifdef CONFIG_TESTING_OPTIONS
352 if (wpa_auth->conf.skip_send_eapol)
353 return 0;
354#endif
Paul Stewart092955c2017-02-06 09:13:09 -0800355 return wpa_auth->cb->send_eapol(wpa_auth->cb_ctx, addr, data, data_len,
356 encrypt);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700357}
358
359
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800360#ifdef CONFIG_MESH
361static inline int wpa_auth_start_ampe(struct wpa_authenticator *wpa_auth,
362 const u8 *addr)
363{
Hai Shalomfdcde762020-04-02 11:19:20 -0700364 if (!wpa_auth->cb->start_ampe)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800365 return -1;
Paul Stewart092955c2017-02-06 09:13:09 -0800366 return wpa_auth->cb->start_ampe(wpa_auth->cb_ctx, addr);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800367}
368#endif /* CONFIG_MESH */
369
370
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700371int wpa_auth_for_each_sta(struct wpa_authenticator *wpa_auth,
372 int (*cb)(struct wpa_state_machine *sm, void *ctx),
373 void *cb_ctx)
374{
Hai Shalomfdcde762020-04-02 11:19:20 -0700375 if (!wpa_auth->cb->for_each_sta)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700376 return 0;
Paul Stewart092955c2017-02-06 09:13:09 -0800377 return wpa_auth->cb->for_each_sta(wpa_auth->cb_ctx, cb, cb_ctx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700378}
379
380
381int wpa_auth_for_each_auth(struct wpa_authenticator *wpa_auth,
382 int (*cb)(struct wpa_authenticator *a, void *ctx),
383 void *cb_ctx)
384{
Hai Shalomfdcde762020-04-02 11:19:20 -0700385 if (!wpa_auth->cb->for_each_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700386 return 0;
Paul Stewart092955c2017-02-06 09:13:09 -0800387 return wpa_auth->cb->for_each_auth(wpa_auth->cb_ctx, cb, cb_ctx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700388}
389
390
Hai Shalom60840252021-02-19 19:02:11 -0800391void wpa_auth_store_ptksa(struct wpa_authenticator *wpa_auth,
392 const u8 *addr, int cipher,
393 u32 life_time, const struct wpa_ptk *ptk)
394{
395 if (wpa_auth->cb->store_ptksa)
396 wpa_auth->cb->store_ptksa(wpa_auth->cb_ctx, addr, cipher,
397 life_time, ptk);
398}
399
400
Sunil Raviaf8751c2023-03-29 11:35:17 -0700401static void wpa_auth_remove_ptksa(struct wpa_authenticator *wpa_auth,
402 const u8 *addr, int cipher)
Hai Shalom60840252021-02-19 19:02:11 -0800403{
404 if (wpa_auth->cb->clear_ptksa)
405 wpa_auth->cb->clear_ptksa(wpa_auth->cb_ctx, addr, cipher);
406}
407
Sunil Raviaf8751c2023-03-29 11:35:17 -0700408
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700409void wpa_auth_logger(struct wpa_authenticator *wpa_auth, const u8 *addr,
410 logger_level level, const char *txt)
411{
Hai Shalomfdcde762020-04-02 11:19:20 -0700412 if (!wpa_auth->cb->logger)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700413 return;
Paul Stewart092955c2017-02-06 09:13:09 -0800414 wpa_auth->cb->logger(wpa_auth->cb_ctx, addr, level, txt);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700415}
416
417
418void wpa_auth_vlogger(struct wpa_authenticator *wpa_auth, const u8 *addr,
419 logger_level level, const char *fmt, ...)
420{
421 char *format;
422 int maxlen;
423 va_list ap;
424
Hai Shalomfdcde762020-04-02 11:19:20 -0700425 if (!wpa_auth->cb->logger)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700426 return;
427
428 maxlen = os_strlen(fmt) + 100;
429 format = os_malloc(maxlen);
430 if (!format)
431 return;
432
433 va_start(ap, fmt);
434 vsnprintf(format, maxlen, fmt, ap);
435 va_end(ap);
436
437 wpa_auth_logger(wpa_auth, addr, level, format);
438
439 os_free(format);
440}
441
442
443static void wpa_sta_disconnect(struct wpa_authenticator *wpa_auth,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700444 const u8 *addr, u16 reason)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700445{
Hai Shalomfdcde762020-04-02 11:19:20 -0700446 if (!wpa_auth->cb->disconnect)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700447 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700448 wpa_printf(MSG_DEBUG, "wpa_sta_disconnect STA " MACSTR " (reason %u)",
449 MAC2STR(addr), reason);
450 wpa_auth->cb->disconnect(wpa_auth->cb_ctx, addr, reason);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700451}
452
453
Hai Shalom74f70d42019-02-11 14:42:39 -0800454#ifdef CONFIG_OCV
455static int wpa_channel_info(struct wpa_authenticator *wpa_auth,
456 struct wpa_channel_info *ci)
457{
458 if (!wpa_auth->cb->channel_info)
459 return -1;
460 return wpa_auth->cb->channel_info(wpa_auth->cb_ctx, ci);
461}
462#endif /* CONFIG_OCV */
463
464
Hai Shalom021b0b52019-04-10 11:17:58 -0700465static int wpa_auth_update_vlan(struct wpa_authenticator *wpa_auth,
466 const u8 *addr, int vlan_id)
467{
468 if (!wpa_auth->cb->update_vlan)
469 return -1;
470 return wpa_auth->cb->update_vlan(wpa_auth->cb_ctx, addr, vlan_id);
471}
472
473
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700474static void wpa_rekey_gmk(void *eloop_ctx, void *timeout_ctx)
475{
476 struct wpa_authenticator *wpa_auth = eloop_ctx;
477
478 if (random_get_bytes(wpa_auth->group->GMK, WPA_GMK_LEN)) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700479 wpa_printf(MSG_ERROR,
480 "Failed to get random data for WPA initialization.");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700481 } else {
482 wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "GMK rekeyd");
483 wpa_hexdump_key(MSG_DEBUG, "GMK",
484 wpa_auth->group->GMK, WPA_GMK_LEN);
485 }
486
487 if (wpa_auth->conf.wpa_gmk_rekey) {
488 eloop_register_timeout(wpa_auth->conf.wpa_gmk_rekey, 0,
489 wpa_rekey_gmk, wpa_auth, NULL);
490 }
491}
492
493
Sunil Ravi7f769292024-07-23 22:21:32 +0000494static void wpa_rekey_all_groups(struct wpa_authenticator *wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700495{
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700496 struct wpa_group *group, *next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700497
498 wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "rekeying GTK");
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700499 group = wpa_auth->group;
500 while (group) {
Sunil Ravi7f769292024-07-23 22:21:32 +0000501 wpa_printf(MSG_DEBUG, "GTK rekey start for authenticator ("
502 MACSTR "), group vlan %d",
503 MAC2STR(wpa_auth->addr), group->vlan_id);
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700504 wpa_group_get(wpa_auth, group);
505
Hai Shalome21d4e82020-04-29 16:34:06 -0700506 group->GTKReKey = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700507 do {
Hai Shalome21d4e82020-04-29 16:34:06 -0700508 group->changed = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700509 wpa_group_sm_step(wpa_auth, group);
510 } while (group->changed);
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700511
512 next = group->next;
513 wpa_group_put(wpa_auth, group);
514 group = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700515 }
Sunil Ravi7f769292024-07-23 22:21:32 +0000516}
517
518
519#ifdef CONFIG_IEEE80211BE
520
521static void wpa_update_all_gtks(struct wpa_authenticator *wpa_auth)
522{
523 struct wpa_group *group, *next;
524
525 group = wpa_auth->group;
526 while (group) {
527 wpa_group_get(wpa_auth, group);
528
529 wpa_group_update_gtk(wpa_auth, group);
530 next = group->next;
531 wpa_group_put(wpa_auth, group);
532 group = next;
533 }
534}
535
536
537static int wpa_update_all_gtks_cb(struct wpa_authenticator *wpa_auth, void *ctx)
538{
539 const u8 *mld_addr = ctx;
540
541 if (!ether_addr_equal(wpa_auth->mld_addr, mld_addr))
542 return 0;
543
544 wpa_update_all_gtks(wpa_auth);
545 return 0;
546}
547
548
549static int wpa_rekey_all_groups_cb(struct wpa_authenticator *wpa_auth,
550 void *ctx)
551{
552 const u8 *mld_addr = ctx;
553
554 if (!ether_addr_equal(wpa_auth->mld_addr, mld_addr))
555 return 0;
556
557 wpa_rekey_all_groups(wpa_auth);
558 return 0;
559}
560
561#endif /* CONFIG_IEEE80211BE */
562
563
564static void wpa_rekey_gtk(void *eloop_ctx, void *timeout_ctx)
565{
566 struct wpa_authenticator *wpa_auth = eloop_ctx;
567
568#ifdef CONFIG_IEEE80211BE
569 if (wpa_auth->is_ml) {
570 /* Non-primary ML authenticator eloop timer for group rekey is
571 * never started and shouldn't fire. Check and warn just in
572 * case. */
573 if (!wpa_auth->primary_auth) {
574 wpa_printf(MSG_DEBUG,
575 "RSN: Cannot start GTK rekey on non-primary ML authenticator");
576 return;
577 }
578
579 /* Generate all the new group keys */
580 wpa_auth_for_each_auth(wpa_auth, wpa_update_all_gtks_cb,
581 wpa_auth->mld_addr);
582
583 /* Send all the generated group keys to the respective stations
584 * with group key handshake. */
585 wpa_auth_for_each_auth(wpa_auth, wpa_rekey_all_groups_cb,
586 wpa_auth->mld_addr);
587 } else {
588 wpa_rekey_all_groups(wpa_auth);
589 }
590#else /* CONFIG_IEEE80211BE */
591 wpa_rekey_all_groups(wpa_auth);
592#endif /* CONFIG_IEEE80211BE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700593
594 if (wpa_auth->conf.wpa_group_rekey) {
595 eloop_register_timeout(wpa_auth->conf.wpa_group_rekey,
596 0, wpa_rekey_gtk, wpa_auth, NULL);
597 }
598}
599
600
601static void wpa_rekey_ptk(void *eloop_ctx, void *timeout_ctx)
602{
603 struct wpa_authenticator *wpa_auth = eloop_ctx;
604 struct wpa_state_machine *sm = timeout_ctx;
605
Sunil Raviaf8751c2023-03-29 11:35:17 -0700606 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
607 "rekeying PTK");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700608 wpa_request_new_ptk(sm);
609 wpa_sm_step(sm);
610}
611
612
Hai Shalom81f62d82019-07-22 12:10:00 -0700613void wpa_auth_set_ptk_rekey_timer(struct wpa_state_machine *sm)
614{
615 if (sm && sm->wpa_auth->conf.wpa_ptk_rekey) {
616 wpa_printf(MSG_DEBUG, "WPA: Start PTK rekeying timer for "
Sunil Raviaf8751c2023-03-29 11:35:17 -0700617 MACSTR " (%d seconds)",
618 MAC2STR(wpa_auth_get_spa(sm)),
Hai Shalom81f62d82019-07-22 12:10:00 -0700619 sm->wpa_auth->conf.wpa_ptk_rekey);
620 eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm);
621 eloop_register_timeout(sm->wpa_auth->conf.wpa_ptk_rekey, 0,
622 wpa_rekey_ptk, sm->wpa_auth, sm);
623 }
624}
625
626
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700627static int wpa_auth_pmksa_clear_cb(struct wpa_state_machine *sm, void *ctx)
628{
629 if (sm->pmksa == ctx)
630 sm->pmksa = NULL;
631 return 0;
632}
633
634
635static void wpa_auth_pmksa_free_cb(struct rsn_pmksa_cache_entry *entry,
636 void *ctx)
637{
638 struct wpa_authenticator *wpa_auth = ctx;
639 wpa_auth_for_each_sta(wpa_auth, wpa_auth_pmksa_clear_cb, entry);
640}
641
642
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700643static int wpa_group_init_gmk_and_counter(struct wpa_authenticator *wpa_auth,
644 struct wpa_group *group)
645{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800646 u8 buf[ETH_ALEN + 8 + sizeof(unsigned long)];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700647 u8 rkey[32];
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800648 unsigned long ptr;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700649
650 if (random_get_bytes(group->GMK, WPA_GMK_LEN) < 0)
651 return -1;
652 wpa_hexdump_key(MSG_DEBUG, "GMK", group->GMK, WPA_GMK_LEN);
653
654 /*
655 * Counter = PRF-256(Random number, "Init Counter",
656 * Local MAC Address || Time)
657 */
658 os_memcpy(buf, wpa_auth->addr, ETH_ALEN);
659 wpa_get_ntp_timestamp(buf + ETH_ALEN);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800660 ptr = (unsigned long) group;
661 os_memcpy(buf + ETH_ALEN + 8, &ptr, sizeof(ptr));
Hai Shalom74f70d42019-02-11 14:42:39 -0800662#ifdef TEST_FUZZ
663 os_memset(buf + ETH_ALEN, 0xab, 8);
664 os_memset(buf + ETH_ALEN + 8, 0xcd, sizeof(ptr));
665#endif /* TEST_FUZZ */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700666 if (random_get_bytes(rkey, sizeof(rkey)) < 0)
667 return -1;
668
669 if (sha1_prf(rkey, sizeof(rkey), "Init Counter", buf, sizeof(buf),
670 group->Counter, WPA_NONCE_LEN) < 0)
671 return -1;
672 wpa_hexdump_key(MSG_DEBUG, "Key Counter",
673 group->Counter, WPA_NONCE_LEN);
674
675 return 0;
676}
677
678
679static struct wpa_group * wpa_group_init(struct wpa_authenticator *wpa_auth,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800680 int vlan_id, int delay_init)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700681{
682 struct wpa_group *group;
683
684 group = os_zalloc(sizeof(struct wpa_group));
Hai Shalomfdcde762020-04-02 11:19:20 -0700685 if (!group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700686 return NULL;
687
Hai Shalome21d4e82020-04-29 16:34:06 -0700688 group->GTKAuthenticator = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700689 group->vlan_id = vlan_id;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -0700690 group->GTK_len = wpa_cipher_key_len(wpa_auth->conf.wpa_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700691
692 if (random_pool_ready() != 1) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700693 wpa_printf(MSG_INFO,
694 "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 -0700695 }
696
697 /*
698 * Set initial GMK/Counter value here. The actual values that will be
699 * used in negotiations will be set once the first station tries to
700 * connect. This allows more time for collecting additional randomness
701 * on embedded devices.
702 */
703 if (wpa_group_init_gmk_and_counter(wpa_auth, group) < 0) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700704 wpa_printf(MSG_ERROR,
705 "Failed to get random data for WPA initialization.");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700706 os_free(group);
707 return NULL;
708 }
709
Hai Shalome21d4e82020-04-29 16:34:06 -0700710 group->GInit = true;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800711 if (delay_init) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700712 wpa_printf(MSG_DEBUG,
713 "WPA: Delay group state machine start until Beacon frames have been configured");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800714 /* Initialization is completed in wpa_init_keys(). */
715 } else {
716 wpa_group_sm_step(wpa_auth, group);
Hai Shalome21d4e82020-04-29 16:34:06 -0700717 group->GInit = false;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800718 wpa_group_sm_step(wpa_auth, group);
719 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700720
721 return group;
722}
723
724
725/**
726 * wpa_init - Initialize WPA authenticator
727 * @addr: Authenticator address
728 * @conf: Configuration for WPA authenticator
729 * @cb: Callback functions for WPA authenticator
730 * Returns: Pointer to WPA authenticator data or %NULL on failure
731 */
732struct wpa_authenticator * wpa_init(const u8 *addr,
733 struct wpa_auth_config *conf,
Paul Stewart092955c2017-02-06 09:13:09 -0800734 const struct wpa_auth_callbacks *cb,
735 void *cb_ctx)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700736{
737 struct wpa_authenticator *wpa_auth;
738
739 wpa_auth = os_zalloc(sizeof(struct wpa_authenticator));
Hai Shalomfdcde762020-04-02 11:19:20 -0700740 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700741 return NULL;
Sunil Ravi7f769292024-07-23 22:21:32 +0000742
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700743 os_memcpy(wpa_auth->addr, addr, ETH_ALEN);
744 os_memcpy(&wpa_auth->conf, conf, sizeof(*conf));
Sunil Ravi7f769292024-07-23 22:21:32 +0000745
746#ifdef CONFIG_IEEE80211BE
747 if (conf->mld_addr) {
748 wpa_auth->is_ml = true;
749 wpa_auth->link_id = conf->link_id;
750 wpa_auth->primary_auth = !conf->first_link_auth;
751 os_memcpy(wpa_auth->mld_addr, conf->mld_addr, ETH_ALEN);
752 }
753#endif /* CONFIG_IEEE80211BE */
754
Paul Stewart092955c2017-02-06 09:13:09 -0800755 wpa_auth->cb = cb;
756 wpa_auth->cb_ctx = cb_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700757
758 if (wpa_auth_gen_wpa_ie(wpa_auth)) {
759 wpa_printf(MSG_ERROR, "Could not generate WPA IE.");
760 os_free(wpa_auth);
761 return NULL;
762 }
763
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800764 wpa_auth->group = wpa_group_init(wpa_auth, 0, 1);
Hai Shalomfdcde762020-04-02 11:19:20 -0700765 if (!wpa_auth->group) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700766 os_free(wpa_auth->wpa_ie);
767 os_free(wpa_auth);
768 return NULL;
769 }
770
771 wpa_auth->pmksa = pmksa_cache_auth_init(wpa_auth_pmksa_free_cb,
772 wpa_auth);
Hai Shalomfdcde762020-04-02 11:19:20 -0700773 if (!wpa_auth->pmksa) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700774 wpa_printf(MSG_ERROR, "PMKSA cache initialization failed.");
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800775 os_free(wpa_auth->group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700776 os_free(wpa_auth->wpa_ie);
777 os_free(wpa_auth);
778 return NULL;
779 }
780
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800781#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700782 wpa_auth->ft_pmk_cache = wpa_ft_pmk_cache_init();
Hai Shalomfdcde762020-04-02 11:19:20 -0700783 if (!wpa_auth->ft_pmk_cache) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700784 wpa_printf(MSG_ERROR, "FT PMK cache initialization failed.");
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800785 os_free(wpa_auth->group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700786 os_free(wpa_auth->wpa_ie);
787 pmksa_cache_auth_deinit(wpa_auth->pmksa);
788 os_free(wpa_auth);
789 return NULL;
790 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800791#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700792
793 if (wpa_auth->conf.wpa_gmk_rekey) {
794 eloop_register_timeout(wpa_auth->conf.wpa_gmk_rekey, 0,
795 wpa_rekey_gmk, wpa_auth, NULL);
796 }
797
Sunil Ravi7f769292024-07-23 22:21:32 +0000798#ifdef CONFIG_IEEE80211BE
799 /* For AP MLD, run group rekey timer only on one link (first) and
800 * whenever it fires do rekey on all associated ML links in one shot.
801 */
802 if ((!wpa_auth->is_ml || !conf->first_link_auth) &&
803 wpa_auth->conf.wpa_group_rekey) {
804#else /* CONFIG_IEEE80211BE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700805 if (wpa_auth->conf.wpa_group_rekey) {
Sunil Ravi7f769292024-07-23 22:21:32 +0000806#endif /* CONFIG_IEEE80211BE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700807 eloop_register_timeout(wpa_auth->conf.wpa_group_rekey, 0,
808 wpa_rekey_gtk, wpa_auth, NULL);
809 }
810
Dmitry Shmidtcf32e602014-01-28 10:57:39 -0800811#ifdef CONFIG_P2P
812 if (WPA_GET_BE32(conf->ip_addr_start)) {
813 int count = WPA_GET_BE32(conf->ip_addr_end) -
814 WPA_GET_BE32(conf->ip_addr_start) + 1;
815 if (count > 1000)
816 count = 1000;
817 if (count > 0)
818 wpa_auth->ip_pool = bitfield_alloc(count);
819 }
820#endif /* CONFIG_P2P */
821
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000822 if (conf->tx_bss_auth && conf->beacon_prot) {
823 conf->tx_bss_auth->non_tx_beacon_prot = true;
824 if (!conf->tx_bss_auth->conf.beacon_prot)
825 conf->tx_bss_auth->conf.beacon_prot = true;
826 if (!conf->tx_bss_auth->conf.group_mgmt_cipher)
827 conf->tx_bss_auth->conf.group_mgmt_cipher =
828 conf->group_mgmt_cipher;
829 }
830
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700831 return wpa_auth;
832}
833
834
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800835int wpa_init_keys(struct wpa_authenticator *wpa_auth)
836{
837 struct wpa_group *group = wpa_auth->group;
838
Hai Shalomfdcde762020-04-02 11:19:20 -0700839 wpa_printf(MSG_DEBUG,
840 "WPA: Start group state machine to set initial keys");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800841 wpa_group_sm_step(wpa_auth, group);
Hai Shalome21d4e82020-04-29 16:34:06 -0700842 group->GInit = false;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800843 wpa_group_sm_step(wpa_auth, group);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800844 if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
845 return -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800846 return 0;
847}
848
849
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000850static void wpa_auth_free_conf(struct wpa_auth_config *conf)
851{
852#ifdef CONFIG_TESTING_OPTIONS
853 wpabuf_free(conf->eapol_m1_elements);
854 conf->eapol_m1_elements = NULL;
855 wpabuf_free(conf->eapol_m3_elements);
856 conf->eapol_m3_elements = NULL;
857#endif /* CONFIG_TESTING_OPTIONS */
858}
859
860
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700861/**
862 * wpa_deinit - Deinitialize WPA authenticator
863 * @wpa_auth: Pointer to WPA authenticator data from wpa_init()
864 */
865void wpa_deinit(struct wpa_authenticator *wpa_auth)
866{
867 struct wpa_group *group, *prev;
868
869 eloop_cancel_timeout(wpa_rekey_gmk, wpa_auth, NULL);
Sunil Ravi7f769292024-07-23 22:21:32 +0000870
871 /* TODO: Assign ML primary authenticator to next link authenticator and
872 * start rekey timer. */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700873 eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL);
874
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700875 pmksa_cache_auth_deinit(wpa_auth->pmksa);
876
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800877#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700878 wpa_ft_pmk_cache_deinit(wpa_auth->ft_pmk_cache);
879 wpa_auth->ft_pmk_cache = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700880 wpa_ft_deinit(wpa_auth);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800881#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700882
Dmitry Shmidtcf32e602014-01-28 10:57:39 -0800883#ifdef CONFIG_P2P
884 bitfield_free(wpa_auth->ip_pool);
885#endif /* CONFIG_P2P */
886
887
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700888 os_free(wpa_auth->wpa_ie);
889
890 group = wpa_auth->group;
891 while (group) {
892 prev = group;
893 group = group->next;
Sunil Ravia04bd252022-05-02 22:54:18 -0700894 bin_clear_free(prev, sizeof(*prev));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700895 }
896
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000897 wpa_auth_free_conf(&wpa_auth->conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700898 os_free(wpa_auth);
899}
900
901
902/**
903 * wpa_reconfig - Update WPA authenticator configuration
904 * @wpa_auth: Pointer to WPA authenticator data from wpa_init()
905 * @conf: Configuration for WPA authenticator
906 */
907int wpa_reconfig(struct wpa_authenticator *wpa_auth,
908 struct wpa_auth_config *conf)
909{
910 struct wpa_group *group;
Hai Shalomfdcde762020-04-02 11:19:20 -0700911
912 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700913 return 0;
914
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000915 wpa_auth_free_conf(&wpa_auth->conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700916 os_memcpy(&wpa_auth->conf, conf, sizeof(*conf));
917 if (wpa_auth_gen_wpa_ie(wpa_auth)) {
918 wpa_printf(MSG_ERROR, "Could not generate WPA IE.");
919 return -1;
920 }
921
922 /*
923 * Reinitialize GTK to make sure it is suitable for the new
924 * configuration.
925 */
926 group = wpa_auth->group;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -0700927 group->GTK_len = wpa_cipher_key_len(wpa_auth->conf.wpa_group);
Hai Shalome21d4e82020-04-29 16:34:06 -0700928 group->GInit = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700929 wpa_group_sm_step(wpa_auth, group);
Hai Shalome21d4e82020-04-29 16:34:06 -0700930 group->GInit = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700931 wpa_group_sm_step(wpa_auth, group);
932
933 return 0;
934}
935
936
937struct wpa_state_machine *
Dmitry Shmidt391c59f2013-09-03 12:16:28 -0700938wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr,
939 const u8 *p2p_dev_addr)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700940{
941 struct wpa_state_machine *sm;
942
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800943 if (wpa_auth->group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
944 return NULL;
945
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700946 sm = os_zalloc(sizeof(struct wpa_state_machine));
Hai Shalomfdcde762020-04-02 11:19:20 -0700947 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700948 return NULL;
949 os_memcpy(sm->addr, addr, ETH_ALEN);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -0700950 if (p2p_dev_addr)
951 os_memcpy(sm->p2p_dev_addr, p2p_dev_addr, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700952
953 sm->wpa_auth = wpa_auth;
954 sm->group = wpa_auth->group;
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700955 wpa_group_get(sm->wpa_auth, sm->group);
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000956#ifdef CONFIG_IEEE80211BE
957 sm->mld_assoc_link_id = -1;
958#endif /* CONFIG_IEEE80211BE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700959
960 return sm;
961}
962
963
964int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth,
965 struct wpa_state_machine *sm)
966{
Hai Shalomfdcde762020-04-02 11:19:20 -0700967 if (!wpa_auth || !wpa_auth->conf.wpa || !sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700968 return -1;
969
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800970#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700971 if (sm->ft_completed) {
Sunil Raviaf8751c2023-03-29 11:35:17 -0700972 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -0700973 "FT authentication already completed - do not start 4-way handshake");
Dmitry Shmidt71757432014-06-02 13:50:35 -0700974 /* Go to PTKINITDONE state to allow GTK rekeying */
975 sm->wpa_ptk_state = WPA_PTK_PTKINITDONE;
Hai Shalome21d4e82020-04-29 16:34:06 -0700976 sm->Pair = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700977 return 0;
978 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800979#endif /* CONFIG_IEEE80211R_AP */
980
981#ifdef CONFIG_FILS
982 if (sm->fils_completed) {
Sunil Raviaf8751c2023-03-29 11:35:17 -0700983 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800984 "FILS authentication already completed - do not start 4-way handshake");
985 /* Go to PTKINITDONE state to allow GTK rekeying */
986 sm->wpa_ptk_state = WPA_PTK_PTKINITDONE;
Hai Shalome21d4e82020-04-29 16:34:06 -0700987 sm->Pair = true;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800988 return 0;
989 }
990#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700991
992 if (sm->started) {
993 os_memset(&sm->key_replay, 0, sizeof(sm->key_replay));
Hai Shalome21d4e82020-04-29 16:34:06 -0700994 sm->ReAuthenticationRequest = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700995 return wpa_sm_step(sm);
996 }
997
Sunil Raviaf8751c2023-03-29 11:35:17 -0700998 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700999 "start authentication");
1000 sm->started = 1;
1001
Hai Shalome21d4e82020-04-29 16:34:06 -07001002 sm->Init = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001003 if (wpa_sm_step(sm) == 1)
1004 return 1; /* should not really happen */
Hai Shalome21d4e82020-04-29 16:34:06 -07001005 sm->Init = false;
1006 sm->AuthenticationRequest = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001007 return wpa_sm_step(sm);
1008}
1009
1010
1011void wpa_auth_sta_no_wpa(struct wpa_state_machine *sm)
1012{
1013 /* WPA/RSN was not used - clear WPA state. This is needed if the STA
1014 * reassociates back to the same AP while the previous entry for the
1015 * STA has not yet been removed. */
Hai Shalomfdcde762020-04-02 11:19:20 -07001016 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001017 return;
1018
1019 sm->wpa_key_mgmt = 0;
1020}
1021
1022
1023static void wpa_free_sta_sm(struct wpa_state_machine *sm)
1024{
Sunil Ravi7f769292024-07-23 22:21:32 +00001025#ifdef CONFIG_IEEE80211BE
1026 int link_id;
1027#endif /* CONFIG_IEEE80211BE */
1028
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001029#ifdef CONFIG_P2P
1030 if (WPA_GET_BE32(sm->ip_addr)) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001031 wpa_printf(MSG_DEBUG,
1032 "P2P: Free assigned IP address %u.%u.%u.%u from "
Sunil8cd6f4d2022-06-28 18:40:46 +00001033 MACSTR " (bit %u)",
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001034 sm->ip_addr[0], sm->ip_addr[1],
1035 sm->ip_addr[2], sm->ip_addr[3],
Sunil Raviaf8751c2023-03-29 11:35:17 -07001036 MAC2STR(wpa_auth_get_spa(sm)),
1037 sm->ip_addr_bit);
Sunil8cd6f4d2022-06-28 18:40:46 +00001038 bitfield_clear(sm->wpa_auth->ip_pool, sm->ip_addr_bit);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001039 }
1040#endif /* CONFIG_P2P */
Sunil Ravi7f769292024-07-23 22:21:32 +00001041 if (sm->GUpdateStationKeys)
1042 wpa_gkeydone_sta(sm);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001043#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001044 os_free(sm->assoc_resp_ftie);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07001045 wpabuf_free(sm->ft_pending_req_ies);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001046#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001047 os_free(sm->last_rx_eapol_key);
1048 os_free(sm->wpa_ie);
Hai Shalomc3565922019-10-28 11:58:20 -07001049 os_free(sm->rsnxe);
Sunil Ravic0f5d412024-09-11 22:12:49 +00001050 os_free(sm->rsn_selection);
Sunil Ravi7f769292024-07-23 22:21:32 +00001051#ifdef CONFIG_IEEE80211BE
1052 for_each_sm_auth(sm, link_id) {
1053 wpa_group_put(sm->mld_links[link_id].wpa_auth,
1054 sm->mld_links[link_id].wpa_auth->group);
1055 sm->mld_links[link_id].wpa_auth = NULL;
1056 }
1057#endif /* CONFIG_IEEE80211BE */
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07001058 wpa_group_put(sm->wpa_auth, sm->group);
Hai Shalom021b0b52019-04-10 11:17:58 -07001059#ifdef CONFIG_DPP2
1060 wpabuf_clear_free(sm->dpp_z);
1061#endif /* CONFIG_DPP2 */
Hai Shalom1dc4d202019-04-29 16:22:27 -07001062 bin_clear_free(sm, sizeof(*sm));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001063}
1064
1065
1066void wpa_auth_sta_deinit(struct wpa_state_machine *sm)
1067{
Hai Shalomfdcde762020-04-02 11:19:20 -07001068 struct wpa_authenticator *wpa_auth;
1069
1070 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001071 return;
1072
Hai Shalomfdcde762020-04-02 11:19:20 -07001073 wpa_auth = sm->wpa_auth;
1074 if (wpa_auth->conf.wpa_strict_rekey && sm->has_GTK) {
Sunil Ravi7f769292024-07-23 22:21:32 +00001075 struct wpa_authenticator *primary_auth = wpa_auth;
1076
Sunil Raviaf8751c2023-03-29 11:35:17 -07001077 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07001078 "strict rekeying - force GTK rekey since STA is leaving");
Sunil Ravi7f769292024-07-23 22:21:32 +00001079
1080#ifdef CONFIG_IEEE80211BE
1081 if (wpa_auth->is_ml && !wpa_auth->primary_auth)
1082 primary_auth = wpa_get_primary_auth(wpa_auth);
1083#endif /* CONFIG_IEEE80211BE */
1084
Roshan Pius3a1667e2018-07-03 15:17:14 -07001085 if (eloop_deplete_timeout(0, 500000, wpa_rekey_gtk,
Sunil Ravi7f769292024-07-23 22:21:32 +00001086 primary_auth, NULL) == -1)
Hai Shalomfdcde762020-04-02 11:19:20 -07001087 eloop_register_timeout(0, 500000, wpa_rekey_gtk,
Sunil Ravi7f769292024-07-23 22:21:32 +00001088 primary_auth, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001089 }
1090
Hai Shalomfdcde762020-04-02 11:19:20 -07001091 eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001092 sm->pending_1_of_4_timeout = 0;
1093 eloop_cancel_timeout(wpa_sm_call_step, sm, NULL);
Hai Shalomfdcde762020-04-02 11:19:20 -07001094 eloop_cancel_timeout(wpa_rekey_ptk, wpa_auth, sm);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001095#ifdef CONFIG_IEEE80211R_AP
1096 wpa_ft_sta_deinit(sm);
1097#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001098 if (sm->in_step_loop) {
1099 /* Must not free state machine while wpa_sm_step() is running.
1100 * Freeing will be completed in the end of wpa_sm_step(). */
Hai Shalomfdcde762020-04-02 11:19:20 -07001101 wpa_printf(MSG_DEBUG,
1102 "WPA: Registering pending STA state machine deinit for "
Sunil Raviaf8751c2023-03-29 11:35:17 -07001103 MACSTR, MAC2STR(wpa_auth_get_spa(sm)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001104 sm->pending_deinit = 1;
1105 } else
1106 wpa_free_sta_sm(sm);
1107}
1108
1109
1110static void wpa_request_new_ptk(struct wpa_state_machine *sm)
1111{
Hai Shalomfdcde762020-04-02 11:19:20 -07001112 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001113 return;
1114
Hai Shalomfdcde762020-04-02 11:19:20 -07001115 if (!sm->use_ext_key_id && sm->wpa_auth->conf.wpa_deny_ptk0_rekey) {
1116 wpa_printf(MSG_INFO,
1117 "WPA: PTK0 rekey not allowed, disconnect " MACSTR,
Sunil Raviaf8751c2023-03-29 11:35:17 -07001118 MAC2STR(wpa_auth_get_spa(sm)));
Hai Shalome21d4e82020-04-29 16:34:06 -07001119 sm->Disconnect = true;
Hai Shalomfdcde762020-04-02 11:19:20 -07001120 /* Try to encourage the STA to reconnect */
1121 sm->disconnect_reason =
1122 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA;
1123 } else {
1124 if (sm->use_ext_key_id)
1125 sm->keyidx_active ^= 1; /* flip Key ID */
Hai Shalome21d4e82020-04-29 16:34:06 -07001126 sm->PTKRequest = true;
Hai Shalomfdcde762020-04-02 11:19:20 -07001127 sm->PTK_valid = 0;
1128 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001129}
1130
1131
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001132static int wpa_replay_counter_valid(struct wpa_key_replay_counter *ctr,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001133 const u8 *replay_counter)
1134{
1135 int i;
1136 for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001137 if (!ctr[i].valid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001138 break;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001139 if (os_memcmp(replay_counter, ctr[i].counter,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001140 WPA_REPLAY_COUNTER_LEN) == 0)
1141 return 1;
1142 }
1143 return 0;
1144}
1145
1146
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001147static void wpa_replay_counter_mark_invalid(struct wpa_key_replay_counter *ctr,
1148 const u8 *replay_counter)
1149{
1150 int i;
1151 for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) {
1152 if (ctr[i].valid &&
Hai Shalomfdcde762020-04-02 11:19:20 -07001153 (!replay_counter ||
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001154 os_memcmp(replay_counter, ctr[i].counter,
1155 WPA_REPLAY_COUNTER_LEN) == 0))
Hai Shalome21d4e82020-04-29 16:34:06 -07001156 ctr[i].valid = false;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001157 }
1158}
1159
1160
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001161#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001162static int ft_check_msg_2_of_4(struct wpa_authenticator *wpa_auth,
1163 struct wpa_state_machine *sm,
1164 struct wpa_eapol_ie_parse *kde)
1165{
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001166 struct wpa_ie_data ie, assoc_ie;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001167 struct rsn_mdie *mdie;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001168 unsigned int i, j;
1169 bool found = false;
1170
1171 /* Verify that PMKR1Name from EAPOL-Key message 2/4 matches the value
1172 * we derived. */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001173
1174 if (wpa_parse_wpa_ie_rsn(kde->rsn_ie, kde->rsn_ie_len, &ie) < 0 ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001175 ie.num_pmkid < 1 || !ie.pmkid) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001176 wpa_printf(MSG_DEBUG,
1177 "FT: No PMKR1Name in FT 4-way handshake message 2/4");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001178 return -1;
1179 }
1180
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001181 if (wpa_parse_wpa_ie_rsn(sm->wpa_ie, sm->wpa_ie_len, &assoc_ie) < 0) {
1182 wpa_printf(MSG_DEBUG,
1183 "FT: Could not parse (Re)Association Request frame RSNE");
1184 os_memset(&assoc_ie, 0, sizeof(assoc_ie));
1185 /* Continue to allow PMKR1Name matching to be done to cover the
1186 * case where it is the only listed PMKID. */
1187 }
1188
1189 for (i = 0; i < ie.num_pmkid; i++) {
1190 const u8 *pmkid = ie.pmkid + i * PMKID_LEN;
1191
1192 if (os_memcmp_const(pmkid, sm->pmk_r1_name,
1193 WPA_PMK_NAME_LEN) == 0) {
1194 wpa_printf(MSG_DEBUG,
1195 "FT: RSNE[PMKID[%u]] from supplicant matches PMKR1Name",
1196 i);
1197 found = true;
1198 } else {
1199 for (j = 0; j < assoc_ie.num_pmkid; j++) {
1200 if (os_memcmp(pmkid,
1201 assoc_ie.pmkid + j * PMKID_LEN,
1202 PMKID_LEN) == 0)
1203 break;
1204 }
1205
1206 if (j == assoc_ie.num_pmkid) {
1207 wpa_printf(MSG_DEBUG,
1208 "FT: RSNE[PMKID[%u]] from supplicant is neither PMKR1Name nor included in AssocReq",
1209 i);
1210 found = false;
1211 break;
1212 }
1213 wpa_printf(MSG_DEBUG,
1214 "FT: RSNE[PMKID[%u]] from supplicant is not PMKR1Name, but matches a PMKID in AssocReq",
1215 i);
1216 }
1217 }
1218
1219 if (!found) {
1220 wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm),
1221 LOGGER_DEBUG,
1222 "PMKR1Name mismatch in FT 4-way handshake");
1223 wpa_hexdump(MSG_DEBUG,
1224 "FT: PMKIDs/PMKR1Name from Supplicant",
1225 ie.pmkid, ie.num_pmkid * PMKID_LEN);
1226 wpa_hexdump(MSG_DEBUG, "FT: Derived PMKR1Name",
1227 sm->pmk_r1_name, WPA_PMK_NAME_LEN);
1228 return -1;
1229 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001230
1231 if (!kde->mdie || !kde->ftie) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001232 wpa_printf(MSG_DEBUG,
1233 "FT: No %s in FT 4-way handshake message 2/4",
1234 kde->mdie ? "FTIE" : "MDIE");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001235 return -1;
1236 }
1237
1238 mdie = (struct rsn_mdie *) (kde->mdie + 2);
1239 if (kde->mdie[1] < sizeof(struct rsn_mdie) ||
1240 os_memcmp(wpa_auth->conf.mobility_domain, mdie->mobility_domain,
1241 MOBILITY_DOMAIN_ID_LEN) != 0) {
1242 wpa_printf(MSG_DEBUG, "FT: MDIE mismatch");
1243 return -1;
1244 }
1245
1246 if (sm->assoc_resp_ftie &&
1247 (kde->ftie[1] != sm->assoc_resp_ftie[1] ||
1248 os_memcmp(kde->ftie, sm->assoc_resp_ftie,
1249 2 + sm->assoc_resp_ftie[1]) != 0)) {
1250 wpa_printf(MSG_DEBUG, "FT: FTIE mismatch");
1251 wpa_hexdump(MSG_DEBUG, "FT: FTIE in EAPOL-Key msg 2/4",
1252 kde->ftie, kde->ftie_len);
1253 wpa_hexdump(MSG_DEBUG, "FT: FTIE in (Re)AssocResp",
1254 sm->assoc_resp_ftie, 2 + sm->assoc_resp_ftie[1]);
1255 return -1;
1256 }
1257
1258 return 0;
1259}
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001260#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001261
1262
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001263static int wpa_receive_error_report(struct wpa_authenticator *wpa_auth,
1264 struct wpa_state_machine *sm, int group)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001265{
1266 /* Supplicant reported a Michael MIC error */
Sunil Raviaf8751c2023-03-29 11:35:17 -07001267 wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001268 "received EAPOL-Key Error Request (STA detected Michael MIC failure (group=%d))",
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001269 group);
1270
1271 if (group && wpa_auth->conf.wpa_group != WPA_CIPHER_TKIP) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07001272 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001273 "ignore Michael MIC failure report since group cipher is not TKIP");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001274 } else if (!group && sm->pairwise != WPA_CIPHER_TKIP) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07001275 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001276 "ignore Michael MIC failure report since pairwise cipher is not TKIP");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001277 } else {
Sunil Raviaf8751c2023-03-29 11:35:17 -07001278 if (wpa_auth_mic_failure_report(wpa_auth,
1279 wpa_auth_get_spa(sm)) > 0)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001280 return 1; /* STA entry was removed */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001281 sm->dot11RSNAStatsTKIPRemoteMICFailures++;
1282 wpa_auth->dot11RSNAStatsTKIPRemoteMICFailures++;
1283 }
1284
1285 /*
1286 * Error report is not a request for a new key handshake, but since
1287 * Authenticator may do it, let's change the keys now anyway.
1288 */
1289 wpa_request_new_ptk(sm);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001290 return 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001291}
1292
1293
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001294static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data,
1295 size_t data_len)
1296{
1297 struct wpa_ptk PTK;
1298 int ok = 0;
1299 const u8 *pmk = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001300 size_t pmk_len;
Hai Shalom021b0b52019-04-10 11:17:58 -07001301 int vlan_id = 0;
Sunil Raviaf8751c2023-03-29 11:35:17 -07001302 u8 pmk_r0[PMK_LEN_MAX], pmk_r0_name[WPA_PMK_NAME_LEN];
1303 u8 pmk_r1[PMK_LEN_MAX];
1304 size_t key_len;
1305 int ret = -1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001306
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001307 os_memset(&PTK, 0, sizeof(PTK));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001308 for (;;) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001309 if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
1310 !wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001311 pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr,
Hai Shalom021b0b52019-04-10 11:17:58 -07001312 sm->p2p_dev_addr, pmk, &pmk_len,
1313 &vlan_id);
Hai Shalomfdcde762020-04-02 11:19:20 -07001314 if (!pmk)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001315 break;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001316#ifdef CONFIG_IEEE80211R_AP
1317 if (wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) {
1318 os_memcpy(sm->xxkey, pmk, pmk_len);
1319 sm->xxkey_len = pmk_len;
1320 }
1321#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001322 } else {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001323 pmk = sm->PMK;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001324 pmk_len = sm->pmk_len;
1325 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001326
Sunil Raviaf8751c2023-03-29 11:35:17 -07001327 if (wpa_derive_ptk(sm, sm->alt_SNonce, pmk, pmk_len, &PTK, 0,
Sunil Ravi7f769292024-07-23 22:21:32 +00001328 pmk_r0, pmk_r1, pmk_r0_name, &key_len,
1329 false) < 0)
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001330 break;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001331
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001332 if (wpa_verify_key_mic(sm->wpa_key_mgmt, pmk_len, &PTK,
1333 data, data_len) == 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001334 if (sm->PMK != pmk) {
1335 os_memcpy(sm->PMK, pmk, pmk_len);
1336 sm->pmk_len = pmk_len;
1337 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001338 ok = 1;
1339 break;
1340 }
1341
Roshan Pius3a1667e2018-07-03 15:17:14 -07001342 if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
1343 wpa_key_mgmt_sae(sm->wpa_key_mgmt))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001344 break;
1345 }
1346
1347 if (!ok) {
1348 wpa_printf(MSG_DEBUG,
1349 "WPA: Earlier SNonce did not result in matching MIC");
Sunil Raviaf8751c2023-03-29 11:35:17 -07001350 goto fail;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001351 }
1352
1353 wpa_printf(MSG_DEBUG,
1354 "WPA: Earlier SNonce resulted in matching MIC");
1355 sm->alt_snonce_valid = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -07001356
1357 if (vlan_id && wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
1358 wpa_auth_update_vlan(sm->wpa_auth, sm->addr, vlan_id) < 0)
Sunil Raviaf8751c2023-03-29 11:35:17 -07001359 goto fail;
1360
1361#ifdef CONFIG_IEEE80211R_AP
1362 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt) && !sm->ft_completed) {
1363 wpa_printf(MSG_DEBUG, "FT: Store PMK-R0/PMK-R1");
1364 wpa_auth_ft_store_keys(sm, pmk_r0, pmk_r1, pmk_r0_name,
1365 key_len);
1366 }
1367#endif /* CONFIG_IEEE80211R_AP */
Hai Shalom021b0b52019-04-10 11:17:58 -07001368
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001369 os_memcpy(sm->SNonce, sm->alt_SNonce, WPA_NONCE_LEN);
1370 os_memcpy(&sm->PTK, &PTK, sizeof(PTK));
Hai Shalom81f62d82019-07-22 12:10:00 -07001371 forced_memzero(&PTK, sizeof(PTK));
Hai Shalome21d4e82020-04-29 16:34:06 -07001372 sm->PTK_valid = true;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001373
Sunil Raviaf8751c2023-03-29 11:35:17 -07001374 ret = 0;
1375fail:
1376 forced_memzero(pmk_r0, sizeof(pmk_r0));
1377 forced_memzero(pmk_r1, sizeof(pmk_r1));
1378 return ret;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001379}
1380
1381
Hai Shaloma20dcd72022-02-04 13:43:00 -08001382static bool wpa_auth_gtk_rekey_in_process(struct wpa_authenticator *wpa_auth)
1383{
1384 struct wpa_group *group;
1385
1386 for (group = wpa_auth->group; group; group = group->next) {
1387 if (group->GKeyDoneStations)
1388 return true;
1389 }
1390 return false;
1391}
1392
1393
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001394enum eapol_key_msg { PAIRWISE_2, PAIRWISE_4, GROUP_2, REQUEST };
1395
1396static bool wpa_auth_valid_key_desc_ver(struct wpa_authenticator *wpa_auth,
1397 struct wpa_state_machine *sm, u16 ver)
1398{
1399 if (ver > WPA_KEY_INFO_TYPE_AES_128_CMAC) {
1400 wpa_printf(MSG_INFO, "RSN: " MACSTR
1401 " used undefined Key Descriptor Version %d",
1402 MAC2STR(wpa_auth_get_spa(sm)), ver);
1403 return false;
1404 }
1405
1406 if (!wpa_use_akm_defined(sm->wpa_key_mgmt) &&
1407 wpa_use_cmac(sm->wpa_key_mgmt) &&
1408 ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) {
1409 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
1410 LOGGER_WARNING,
1411 "advertised support for AES-128-CMAC, but did not use it");
1412 return false;
1413 }
1414
1415 if (sm->pairwise != WPA_CIPHER_TKIP &&
1416 !wpa_use_akm_defined(sm->wpa_key_mgmt) &&
1417 !wpa_use_cmac(sm->wpa_key_mgmt) &&
1418 ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
1419 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
1420 LOGGER_WARNING,
1421 "did not use HMAC-SHA1-AES with CCMP/GCMP");
1422 return false;
1423 }
1424
1425 if (wpa_use_akm_defined(sm->wpa_key_mgmt) &&
1426 ver != WPA_KEY_INFO_TYPE_AKM_DEFINED) {
1427 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
1428 LOGGER_WARNING,
1429 "did not use EAPOL-Key descriptor version 0 as required for AKM-defined cases");
1430 return false;
1431 }
1432
1433 return true;
1434}
1435
1436
1437static bool wpa_auth_valid_request_counter(struct wpa_authenticator *wpa_auth,
1438 struct wpa_state_machine *sm,
1439 const u8 *replay_counter)
1440{
1441
1442 if (sm->req_replay_counter_used &&
1443 os_memcmp(replay_counter, sm->req_replay_counter,
1444 WPA_REPLAY_COUNTER_LEN) <= 0) {
1445 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
1446 LOGGER_WARNING,
1447 "received EAPOL-Key request with replayed counter");
1448 return false;
1449 }
1450
1451 return true;
1452}
1453
1454
1455static bool wpa_auth_valid_counter(struct wpa_authenticator *wpa_auth,
1456 struct wpa_state_machine *sm,
1457 const struct wpa_eapol_key *key,
1458 enum eapol_key_msg msg,
1459 const char *msgtxt)
1460{
1461 int i;
1462
1463 if (msg == REQUEST)
1464 return wpa_auth_valid_request_counter(wpa_auth, sm,
1465 key->replay_counter);
1466
1467 if (wpa_replay_counter_valid(sm->key_replay, key->replay_counter))
1468 return true;
1469
1470 if (msg == PAIRWISE_2 &&
1471 wpa_replay_counter_valid(sm->prev_key_replay,
1472 key->replay_counter) &&
1473 sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING &&
1474 os_memcmp(sm->SNonce, key->key_nonce, WPA_NONCE_LEN) != 0) {
1475 /*
1476 * Some supplicant implementations (e.g., Windows XP
1477 * WZC) update SNonce for each EAPOL-Key 2/4. This
1478 * breaks the workaround on accepting any of the
1479 * pending requests, so allow the SNonce to be updated
1480 * even if we have already sent out EAPOL-Key 3/4.
1481 */
1482 wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
1483 LOGGER_DEBUG,
1484 "Process SNonce update from STA based on retransmitted EAPOL-Key 1/4");
1485 sm->update_snonce = 1;
1486 os_memcpy(sm->alt_SNonce, sm->SNonce, WPA_NONCE_LEN);
1487 sm->alt_snonce_valid = true;
1488 os_memcpy(sm->alt_replay_counter,
1489 sm->key_replay[0].counter,
1490 WPA_REPLAY_COUNTER_LEN);
1491 return true;
1492 }
1493
1494 if (msg == PAIRWISE_4 && sm->alt_snonce_valid &&
1495 sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING &&
1496 os_memcmp(key->replay_counter, sm->alt_replay_counter,
1497 WPA_REPLAY_COUNTER_LEN) == 0) {
1498 /*
1499 * Supplicant may still be using the old SNonce since
1500 * there was two EAPOL-Key 2/4 messages and they had
1501 * different SNonce values.
1502 */
1503 wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
1504 LOGGER_DEBUG,
1505 "Try to process received EAPOL-Key 4/4 based on old Replay Counter and SNonce from an earlier EAPOL-Key 1/4");
1506 return true;
1507 }
1508
1509 if (msg == PAIRWISE_2 &&
1510 wpa_replay_counter_valid(sm->prev_key_replay,
1511 key->replay_counter) &&
1512 sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING) {
1513 wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
1514 LOGGER_DEBUG,
1515 "ignore retransmitted EAPOL-Key %s - SNonce did not change",
1516 msgtxt);
1517 } else {
1518 wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
1519 LOGGER_DEBUG,
1520 "received EAPOL-Key %s with unexpected replay counter",
1521 msgtxt);
1522 }
1523 for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) {
1524 if (!sm->key_replay[i].valid)
1525 break;
1526 wpa_hexdump(MSG_DEBUG, "pending replay counter",
1527 sm->key_replay[i].counter,
1528 WPA_REPLAY_COUNTER_LEN);
1529 }
1530 wpa_hexdump(MSG_DEBUG, "received replay counter",
1531 key->replay_counter, WPA_REPLAY_COUNTER_LEN);
1532 return false;
1533}
1534
1535
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001536void wpa_receive(struct wpa_authenticator *wpa_auth,
1537 struct wpa_state_machine *sm,
1538 u8 *data, size_t data_len)
1539{
1540 struct ieee802_1x_hdr *hdr;
1541 struct wpa_eapol_key *key;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001542 u16 key_info, ver, key_data_length;
1543 enum eapol_key_msg msg;
1544 const char *msgtxt;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001545 const u8 *key_data;
1546 size_t keyhdrlen, mic_len;
1547 u8 *mic;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001548 u8 *key_data_buf = NULL;
1549 size_t key_data_buf_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001550
Hai Shalomfdcde762020-04-02 11:19:20 -07001551 if (!wpa_auth || !wpa_auth->conf.wpa || !sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001552 return;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001553
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001554 wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL data", data, data_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001555
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001556 mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001557 keyhdrlen = sizeof(*key) + mic_len + 2;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001558
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001559 if (data_len < sizeof(*hdr) + keyhdrlen) {
1560 wpa_printf(MSG_DEBUG, "WPA: Ignore too short EAPOL-Key frame");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001561 return;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001562 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001563
1564 hdr = (struct ieee802_1x_hdr *) data;
1565 key = (struct wpa_eapol_key *) (hdr + 1);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001566 mic = (u8 *) (key + 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001567 key_info = WPA_GET_BE16(key->key_info);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001568 key_data = mic + mic_len + 2;
1569 key_data_length = WPA_GET_BE16(mic + mic_len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001570 wpa_printf(MSG_DEBUG, "WPA: Received EAPOL-Key from " MACSTR
Hai Shalomfdcde762020-04-02 11:19:20 -07001571 " key_info=0x%x type=%u mic_len=%zu key_data_length=%u",
Sunil Raviaf8751c2023-03-29 11:35:17 -07001572 MAC2STR(wpa_auth_get_spa(sm)), key_info, key->type,
Hai Shalomfdcde762020-04-02 11:19:20 -07001573 mic_len, key_data_length);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001574 wpa_hexdump(MSG_MSGDUMP,
1575 "WPA: EAPOL-Key header (ending before Key MIC)",
1576 key, sizeof(*key));
1577 wpa_hexdump(MSG_MSGDUMP, "WPA: EAPOL-Key Key MIC",
1578 mic, mic_len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001579 if (key_data_length > data_len - sizeof(*hdr) - keyhdrlen) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001580 wpa_printf(MSG_INFO,
1581 "WPA: Invalid EAPOL-Key frame - key_data overflow (%d > %zu)",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001582 key_data_length,
Hai Shalomfdcde762020-04-02 11:19:20 -07001583 data_len - sizeof(*hdr) - keyhdrlen);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001584 return;
1585 }
1586
1587 if (sm->wpa == WPA_VERSION_WPA2) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001588 if (key->type == EAPOL_KEY_TYPE_WPA) {
1589 /*
1590 * Some deployed station implementations seem to send
1591 * msg 4/4 with incorrect type value in WPA2 mode.
1592 */
Hai Shalomfdcde762020-04-02 11:19:20 -07001593 wpa_printf(MSG_DEBUG,
1594 "Workaround: Allow EAPOL-Key with unexpected WPA type in RSN mode");
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001595 } else if (key->type != EAPOL_KEY_TYPE_RSN) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001596 wpa_printf(MSG_DEBUG,
1597 "Ignore EAPOL-Key with unexpected type %d in RSN mode",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001598 key->type);
1599 return;
1600 }
1601 } else {
1602 if (key->type != EAPOL_KEY_TYPE_WPA) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001603 wpa_printf(MSG_DEBUG,
1604 "Ignore EAPOL-Key with unexpected type %d in WPA mode",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001605 key->type);
1606 return;
1607 }
1608 }
1609
1610 wpa_hexdump(MSG_DEBUG, "WPA: Received Key Nonce", key->key_nonce,
1611 WPA_NONCE_LEN);
1612 wpa_hexdump(MSG_DEBUG, "WPA: Received Replay Counter",
1613 key->replay_counter, WPA_REPLAY_COUNTER_LEN);
1614
1615 /* FIX: verify that the EAPOL-Key frame was encrypted if pairwise keys
1616 * are set */
1617
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001618 if (key_info & WPA_KEY_INFO_SMK_MESSAGE) {
1619 wpa_printf(MSG_DEBUG, "WPA: Ignore SMK message");
1620 return;
1621 }
1622
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001623 ver = key_info & WPA_KEY_INFO_TYPE_MASK;
1624 if (!wpa_auth_valid_key_desc_ver(wpa_auth, sm, ver))
1625 goto out;
1626 if (mic_len > 0 && (key_info & WPA_KEY_INFO_ENCR_KEY_DATA) &&
1627 sm->PTK_valid &&
1628 (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
1629 ver == WPA_KEY_INFO_TYPE_AES_128_CMAC ||
1630 wpa_use_aes_key_wrap(sm->wpa_key_mgmt)) &&
1631 key_data_length >= 8 && key_data_length % 8 == 0) {
1632 key_data_length -= 8; /* AES-WRAP adds 8 bytes */
1633 key_data_buf = os_malloc(key_data_length);
1634 if (!key_data_buf)
1635 goto out;
1636 key_data_buf_len = key_data_length;
1637 if (aes_unwrap(sm->PTK.kek, sm->PTK.kek_len,
1638 key_data_length / 8, key_data, key_data_buf)) {
1639 wpa_printf(MSG_INFO,
1640 "RSN: AES unwrap failed - could not decrypt EAPOL-Key key data");
1641 goto out;
1642 }
1643 key_data = key_data_buf;
1644 wpa_hexdump_key(MSG_DEBUG, "RSN: Decrypted EAPOL-Key Key Data",
1645 key_data, key_data_length);
1646 }
1647
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001648 if (key_info & WPA_KEY_INFO_REQUEST) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001649 msg = REQUEST;
1650 msgtxt = "Request";
1651 } else if (!(key_info & WPA_KEY_INFO_KEY_TYPE)) {
1652 msg = GROUP_2;
1653 msgtxt = "2/2 Group";
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001654 } else if (key_data_length == 0 ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001655 (sm->wpa == WPA_VERSION_WPA2 &&
1656 (!(key_info & WPA_KEY_INFO_ENCR_KEY_DATA) ||
1657 key_data_buf) &&
1658 (key_info & WPA_KEY_INFO_SECURE) &&
1659 !get_ie(key_data, key_data_length, WLAN_EID_RSN)) ||
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001660 (mic_len == 0 && (key_info & WPA_KEY_INFO_ENCR_KEY_DATA) &&
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001661 key_data_length == AES_BLOCK_SIZE)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001662 msg = PAIRWISE_4;
1663 msgtxt = "4/4 Pairwise";
1664 } else {
1665 msg = PAIRWISE_2;
1666 msgtxt = "2/4 Pairwise";
1667 }
1668
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001669 if (!wpa_auth_valid_counter(wpa_auth, sm, key, msg, msgtxt))
1670 goto out;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001671
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001672#ifdef CONFIG_FILS
1673 if (sm->wpa == WPA_VERSION_WPA2 && mic_len == 0 &&
1674 !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07001675 wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001676 "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 +00001677 goto out;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001678 }
1679#endif /* CONFIG_FILS */
1680
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001681 switch (msg) {
1682 case PAIRWISE_2:
1683 if (sm->wpa_ptk_state != WPA_PTK_PTKSTART &&
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001684 sm->wpa_ptk_state != WPA_PTK_PTKCALCNEGOTIATING &&
1685 (!sm->update_snonce ||
1686 sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING)) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07001687 wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
1688 LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001689 "received EAPOL-Key msg 2/4 in invalid state (%d) - dropped",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001690 sm->wpa_ptk_state);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001691 goto out;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001692 }
1693 random_add_randomness(key->key_nonce, WPA_NONCE_LEN);
1694 if (sm->group->reject_4way_hs_for_entropy) {
1695 /*
1696 * The system did not have enough entropy to generate
1697 * strong random numbers. Reject the first 4-way
1698 * handshake(s) and collect some entropy based on the
1699 * information from it. Once enough entropy is
1700 * available, the next atempt will trigger GMK/Key
1701 * Counter update and the station will be allowed to
1702 * continue.
1703 */
Hai Shalomfdcde762020-04-02 11:19:20 -07001704 wpa_printf(MSG_DEBUG,
1705 "WPA: Reject 4-way handshake to collect more entropy for random number generation");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001706 random_mark_pool_ready();
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001707 wpa_sta_disconnect(wpa_auth, sm->addr,
1708 WLAN_REASON_PREV_AUTH_NOT_VALID);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001709 goto out;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001710 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001711 break;
1712 case PAIRWISE_4:
1713 if (sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING ||
1714 !sm->PTK_valid) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07001715 wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
1716 LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001717 "received EAPOL-Key msg 4/4 in invalid state (%d) - dropped",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001718 sm->wpa_ptk_state);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001719 goto out;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001720 }
1721 break;
1722 case GROUP_2:
1723 if (sm->wpa_ptk_group_state != WPA_PTK_GROUP_REKEYNEGOTIATING
1724 || !sm->PTK_valid) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07001725 wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
1726 LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001727 "received EAPOL-Key msg 2/2 in invalid state (%d) - dropped",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001728 sm->wpa_ptk_group_state);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001729 goto out;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001730 }
1731 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001732 case REQUEST:
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001733 if (sm->wpa_ptk_state == WPA_PTK_PTKSTART ||
1734 sm->wpa_ptk_state == WPA_PTK_PTKCALCNEGOTIATING ||
1735 sm->wpa_ptk_state == WPA_PTK_PTKCALCNEGOTIATING2 ||
1736 sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING) {
1737 wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
1738 LOGGER_INFO,
1739 "received EAPOL-Key Request in invalid state (%d) - dropped",
1740 sm->wpa_ptk_state);
1741 goto out;
1742 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001743 break;
1744 }
1745
Sunil Raviaf8751c2023-03-29 11:35:17 -07001746 wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001747 "received EAPOL-Key frame (%s)", msgtxt);
1748
1749 if (key_info & WPA_KEY_INFO_ACK) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07001750 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001751 "received invalid EAPOL-Key: Key Ack set");
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001752 goto out;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001753 }
1754
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001755 if (!wpa_key_mgmt_fils(sm->wpa_key_mgmt) &&
1756 !(key_info & WPA_KEY_INFO_MIC)) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07001757 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001758 "received invalid EAPOL-Key: Key MIC not set");
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001759 goto out;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001760 }
1761
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001762#ifdef CONFIG_FILS
1763 if (wpa_key_mgmt_fils(sm->wpa_key_mgmt) &&
1764 (key_info & WPA_KEY_INFO_MIC)) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07001765 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001766 "received invalid EAPOL-Key: Key MIC set");
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001767 goto out;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001768 }
1769#endif /* CONFIG_FILS */
1770
Hai Shalome21d4e82020-04-29 16:34:06 -07001771 sm->MICVerified = false;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001772 if (sm->PTK_valid && !sm->update_snonce) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001773 if (mic_len &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001774 wpa_verify_key_mic(sm->wpa_key_mgmt, sm->pmk_len, &sm->PTK,
1775 data, data_len) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001776 (msg != PAIRWISE_4 || !sm->alt_snonce_valid ||
1777 wpa_try_alt_snonce(sm, data, data_len))) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07001778 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
1779 LOGGER_INFO,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001780 "received EAPOL-Key with invalid MIC");
Hai Shalom74f70d42019-02-11 14:42:39 -08001781#ifdef TEST_FUZZ
1782 wpa_printf(MSG_INFO,
1783 "TEST: Ignore Key MIC failure for fuzz testing");
1784 goto continue_fuzz;
1785#endif /* TEST_FUZZ */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001786 goto out;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001787 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001788#ifdef CONFIG_FILS
1789 if (!mic_len &&
1790 wpa_aead_decrypt(sm, &sm->PTK, data, data_len,
1791 &key_data_length) < 0) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07001792 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
1793 LOGGER_INFO,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001794 "received EAPOL-Key with invalid MIC");
Hai Shalom74f70d42019-02-11 14:42:39 -08001795#ifdef TEST_FUZZ
1796 wpa_printf(MSG_INFO,
1797 "TEST: Ignore Key MIC failure for fuzz testing");
1798 goto continue_fuzz;
1799#endif /* TEST_FUZZ */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001800 goto out;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001801 }
1802#endif /* CONFIG_FILS */
Hai Shalom74f70d42019-02-11 14:42:39 -08001803#ifdef TEST_FUZZ
1804 continue_fuzz:
1805#endif /* TEST_FUZZ */
Hai Shalome21d4e82020-04-29 16:34:06 -07001806 sm->MICVerified = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001807 eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm);
1808 sm->pending_1_of_4_timeout = 0;
1809 }
1810
1811 if (key_info & WPA_KEY_INFO_REQUEST) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001812 if (!(key_info & WPA_KEY_INFO_SECURE)) {
1813 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
1814 LOGGER_INFO,
1815 "received EAPOL-Key request without Secure=1");
1816 goto out;
1817 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001818 if (sm->MICVerified) {
1819 sm->req_replay_counter_used = 1;
1820 os_memcpy(sm->req_replay_counter, key->replay_counter,
1821 WPA_REPLAY_COUNTER_LEN);
1822 } else {
Sunil Raviaf8751c2023-03-29 11:35:17 -07001823 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
1824 LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001825 "received EAPOL-Key request with invalid MIC");
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001826 goto out;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001827 }
1828
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001829 if (key_info & WPA_KEY_INFO_ERROR) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001830 if (wpa_receive_error_report(
1831 wpa_auth, sm,
1832 !(key_info & WPA_KEY_INFO_KEY_TYPE)) > 0)
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001833 goto out; /* STA entry was removed */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001834 } else if (key_info & WPA_KEY_INFO_KEY_TYPE) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07001835 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
1836 LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001837 "received EAPOL-Key Request for new 4-Way Handshake");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001838 wpa_request_new_ptk(sm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001839 } else {
Sunil Raviaf8751c2023-03-29 11:35:17 -07001840 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
1841 LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001842 "received EAPOL-Key Request for GTK rekeying");
Sunil Ravi7f769292024-07-23 22:21:32 +00001843
1844 eloop_cancel_timeout(wpa_rekey_gtk,
1845 wpa_get_primary_auth(wpa_auth),
1846 NULL);
Hai Shaloma20dcd72022-02-04 13:43:00 -08001847 if (wpa_auth_gtk_rekey_in_process(wpa_auth))
1848 wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG,
1849 "skip new GTK rekey - already in process");
1850 else
Sunil Ravi7f769292024-07-23 22:21:32 +00001851 wpa_rekey_gtk(wpa_get_primary_auth(wpa_auth),
1852 NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001853 }
1854 } else {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001855 /* Do not allow the same key replay counter to be reused. */
1856 wpa_replay_counter_mark_invalid(sm->key_replay,
1857 key->replay_counter);
1858
1859 if (msg == PAIRWISE_2) {
1860 /*
1861 * Maintain a copy of the pending EAPOL-Key frames in
1862 * case the EAPOL-Key frame was retransmitted. This is
1863 * needed to allow EAPOL-Key msg 2/4 reply to another
1864 * pending msg 1/4 to update the SNonce to work around
1865 * unexpected supplicant behavior.
1866 */
1867 os_memcpy(sm->prev_key_replay, sm->key_replay,
1868 sizeof(sm->key_replay));
1869 } else {
1870 os_memset(sm->prev_key_replay, 0,
1871 sizeof(sm->prev_key_replay));
1872 }
1873
1874 /*
1875 * Make sure old valid counters are not accepted anymore and
1876 * do not get copied again.
1877 */
1878 wpa_replay_counter_mark_invalid(sm->key_replay, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001879 }
1880
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001881 os_free(sm->last_rx_eapol_key);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001882 sm->last_rx_eapol_key = os_memdup(data, data_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07001883 if (!sm->last_rx_eapol_key)
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001884 goto out;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001885 sm->last_rx_eapol_key_len = data_len;
1886
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001887 sm->rx_eapol_key_secure = !!(key_info & WPA_KEY_INFO_SECURE);
Hai Shalome21d4e82020-04-29 16:34:06 -07001888 sm->EAPOLKeyReceived = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001889 sm->EAPOLKeyPairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE);
1890 sm->EAPOLKeyRequest = !!(key_info & WPA_KEY_INFO_REQUEST);
Sunil Ravic0f5d412024-09-11 22:12:49 +00001891 if (msg == PAIRWISE_2)
1892 os_memcpy(sm->SNonce, key->key_nonce, WPA_NONCE_LEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001893 wpa_sm_step(sm);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001894
1895out:
1896 bin_clear_free(key_data_buf, key_data_buf_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001897}
1898
1899
1900static int wpa_gmk_to_gtk(const u8 *gmk, const char *label, const u8 *addr,
1901 const u8 *gnonce, u8 *gtk, size_t gtk_len)
1902{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001903 u8 data[ETH_ALEN + WPA_NONCE_LEN + 8 + WPA_GTK_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001904 u8 *pos;
1905 int ret = 0;
1906
1907 /* GTK = PRF-X(GMK, "Group key expansion",
1908 * AA || GNonce || Time || random data)
1909 * The example described in the IEEE 802.11 standard uses only AA and
1910 * GNonce as inputs here. Add some more entropy since this derivation
1911 * is done only at the Authenticator and as such, does not need to be
1912 * exactly same.
1913 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001914 os_memset(data, 0, sizeof(data));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001915 os_memcpy(data, addr, ETH_ALEN);
1916 os_memcpy(data + ETH_ALEN, gnonce, WPA_NONCE_LEN);
1917 pos = data + ETH_ALEN + WPA_NONCE_LEN;
1918 wpa_get_ntp_timestamp(pos);
Hai Shalom74f70d42019-02-11 14:42:39 -08001919#ifdef TEST_FUZZ
1920 os_memset(pos, 0xef, 8);
1921#endif /* TEST_FUZZ */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001922 pos += 8;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001923 if (random_get_bytes(pos, gtk_len) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001924 ret = -1;
1925
Roshan Pius3a1667e2018-07-03 15:17:14 -07001926#ifdef CONFIG_SHA384
1927 if (sha384_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data),
1928 gtk, gtk_len) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001929 ret = -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001930#else /* CONFIG_SHA384 */
1931#ifdef CONFIG_SHA256
1932 if (sha256_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data),
1933 gtk, gtk_len) < 0)
1934 ret = -1;
1935#else /* CONFIG_SHA256 */
1936 if (sha1_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data),
1937 gtk, gtk_len) < 0)
1938 ret = -1;
1939#endif /* CONFIG_SHA256 */
1940#endif /* CONFIG_SHA384 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001941
Hai Shalom81f62d82019-07-22 12:10:00 -07001942 forced_memzero(data, sizeof(data));
1943
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001944 return ret;
1945}
1946
1947
1948static void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx)
1949{
1950 struct wpa_authenticator *wpa_auth = eloop_ctx;
1951 struct wpa_state_machine *sm = timeout_ctx;
1952
Sunil Ravia04bd252022-05-02 22:54:18 -07001953 if (sm->waiting_radius_psk) {
1954 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
1955 "Ignore EAPOL-Key timeout while waiting for RADIUS PSK");
1956 return;
1957 }
1958
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001959 sm->pending_1_of_4_timeout = 0;
Sunil Raviaf8751c2023-03-29 11:35:17 -07001960 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
1961 "EAPOL-Key timeout");
Hai Shalome21d4e82020-04-29 16:34:06 -07001962 sm->TimeoutEvt = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001963 wpa_sm_step(sm);
1964}
1965
1966
1967void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
1968 struct wpa_state_machine *sm, int key_info,
1969 const u8 *key_rsc, const u8 *nonce,
1970 const u8 *kde, size_t kde_len,
1971 int keyidx, int encr, int force_version)
1972{
Hai Shalomfdcde762020-04-02 11:19:20 -07001973 struct wpa_auth_config *conf = &wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001974 struct ieee802_1x_hdr *hdr;
1975 struct wpa_eapol_key *key;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001976 size_t len, mic_len, keyhdrlen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001977 int alg;
1978 int key_data_len, pad_len = 0;
1979 u8 *buf, *pos;
1980 int version, pairwise;
1981 int i;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001982 u8 *key_mic, *key_data;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001983
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001984 mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001985 keyhdrlen = sizeof(*key) + mic_len + 2;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001986
1987 len = sizeof(struct ieee802_1x_hdr) + keyhdrlen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001988
1989 if (force_version)
1990 version = force_version;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001991 else if (wpa_use_akm_defined(sm->wpa_key_mgmt))
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001992 version = WPA_KEY_INFO_TYPE_AKM_DEFINED;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001993 else if (wpa_use_cmac(sm->wpa_key_mgmt))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001994 version = WPA_KEY_INFO_TYPE_AES_128_CMAC;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001995 else if (sm->pairwise != WPA_CIPHER_TKIP)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001996 version = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;
1997 else
1998 version = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
1999
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002000 pairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002001
Hai Shalomfdcde762020-04-02 11:19:20 -07002002 wpa_printf(MSG_DEBUG,
2003 "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 -07002004 version,
2005 (key_info & WPA_KEY_INFO_SECURE) ? 1 : 0,
2006 (key_info & WPA_KEY_INFO_MIC) ? 1 : 0,
2007 (key_info & WPA_KEY_INFO_ACK) ? 1 : 0,
2008 (key_info & WPA_KEY_INFO_INSTALL) ? 1 : 0,
Hai Shalomfdcde762020-04-02 11:19:20 -07002009 pairwise, kde_len, keyidx, encr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002010
2011 key_data_len = kde_len;
2012
2013 if ((version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
Roshan Pius3a1667e2018-07-03 15:17:14 -07002014 wpa_use_aes_key_wrap(sm->wpa_key_mgmt) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002015 version == WPA_KEY_INFO_TYPE_AES_128_CMAC) && encr) {
2016 pad_len = key_data_len % 8;
2017 if (pad_len)
2018 pad_len = 8 - pad_len;
2019 key_data_len += pad_len + 8;
2020 }
2021
2022 len += key_data_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002023 if (!mic_len && encr)
2024 len += AES_BLOCK_SIZE;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002025
2026 hdr = os_zalloc(len);
Hai Shalomfdcde762020-04-02 11:19:20 -07002027 if (!hdr)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002028 return;
Hai Shalomfdcde762020-04-02 11:19:20 -07002029 hdr->version = conf->eapol_version;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002030 hdr->type = IEEE802_1X_TYPE_EAPOL_KEY;
2031 hdr->length = host_to_be16(len - sizeof(*hdr));
2032 key = (struct wpa_eapol_key *) (hdr + 1);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002033 key_mic = (u8 *) (key + 1);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002034 key_data = ((u8 *) (hdr + 1)) + keyhdrlen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002035
2036 key->type = sm->wpa == WPA_VERSION_WPA2 ?
2037 EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
2038 key_info |= version;
2039 if (encr && sm->wpa == WPA_VERSION_WPA2)
2040 key_info |= WPA_KEY_INFO_ENCR_KEY_DATA;
2041 if (sm->wpa != WPA_VERSION_WPA2)
2042 key_info |= keyidx << WPA_KEY_INFO_KEY_INDEX_SHIFT;
2043 WPA_PUT_BE16(key->key_info, key_info);
2044
Hai Shalomfdcde762020-04-02 11:19:20 -07002045 alg = pairwise ? sm->pairwise : conf->wpa_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002046 if (sm->wpa == WPA_VERSION_WPA2 && !pairwise)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002047 WPA_PUT_BE16(key->key_length, 0);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002048 else
2049 WPA_PUT_BE16(key->key_length, wpa_cipher_key_len(alg));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002050
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002051 for (i = RSNA_MAX_EAPOL_RETRIES - 1; i > 0; i--) {
2052 sm->key_replay[i].valid = sm->key_replay[i - 1].valid;
2053 os_memcpy(sm->key_replay[i].counter,
2054 sm->key_replay[i - 1].counter,
2055 WPA_REPLAY_COUNTER_LEN);
2056 }
2057 inc_byte_array(sm->key_replay[0].counter, WPA_REPLAY_COUNTER_LEN);
2058 os_memcpy(key->replay_counter, sm->key_replay[0].counter,
2059 WPA_REPLAY_COUNTER_LEN);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002060 wpa_hexdump(MSG_DEBUG, "WPA: Replay Counter",
2061 key->replay_counter, WPA_REPLAY_COUNTER_LEN);
Hai Shalome21d4e82020-04-29 16:34:06 -07002062 sm->key_replay[0].valid = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002063
2064 if (nonce)
2065 os_memcpy(key->key_nonce, nonce, WPA_NONCE_LEN);
2066
2067 if (key_rsc)
2068 os_memcpy(key->key_rsc, key_rsc, WPA_KEY_RSC_LEN);
2069
Sunil Ravic0f5d412024-09-11 22:12:49 +00002070#ifdef CONFIG_TESTING_OPTIONS
2071 if (conf->eapol_key_reserved_random)
2072 random_get_bytes(key->key_id, sizeof(key->key_id));
2073#endif /* CONFIG_TESTING_OPTIONS */
2074
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002075 if (kde && !encr) {
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002076 os_memcpy(key_data, kde, kde_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002077 WPA_PUT_BE16(key_mic + mic_len, kde_len);
2078#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07002079 } else if (!mic_len && kde) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002080 const u8 *aad[1];
2081 size_t aad_len[1];
2082
2083 WPA_PUT_BE16(key_mic, AES_BLOCK_SIZE + kde_len);
2084 wpa_hexdump_key(MSG_DEBUG, "Plaintext EAPOL-Key Key Data",
2085 kde, kde_len);
2086
2087 wpa_hexdump_key(MSG_DEBUG, "WPA: KEK",
2088 sm->PTK.kek, sm->PTK.kek_len);
2089 /* AES-SIV AAD from EAPOL protocol version field (inclusive) to
2090 * to Key Data (exclusive). */
2091 aad[0] = (u8 *) hdr;
2092 aad_len[0] = key_mic + 2 - (u8 *) hdr;
2093 if (aes_siv_encrypt(sm->PTK.kek, sm->PTK.kek_len, kde, kde_len,
2094 1, aad, aad_len, key_mic + 2) < 0) {
2095 wpa_printf(MSG_DEBUG, "WPA: AES-SIV encryption failed");
2096 return;
2097 }
2098
2099 wpa_hexdump(MSG_DEBUG, "WPA: Encrypted Key Data from SIV",
2100 key_mic + 2, AES_BLOCK_SIZE + kde_len);
2101#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002102 } else if (encr && kde) {
2103 buf = os_zalloc(key_data_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07002104 if (!buf) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002105 os_free(hdr);
2106 return;
2107 }
2108 pos = buf;
2109 os_memcpy(pos, kde, kde_len);
2110 pos += kde_len;
2111
2112 if (pad_len)
2113 *pos++ = 0xdd;
2114
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002115 wpa_hexdump_key(MSG_DEBUG,
2116 "Plaintext EAPOL-Key Key Data (+ padding)",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002117 buf, key_data_len);
2118 if (version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
Roshan Pius3a1667e2018-07-03 15:17:14 -07002119 wpa_use_aes_key_wrap(sm->wpa_key_mgmt) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002120 version == WPA_KEY_INFO_TYPE_AES_128_CMAC) {
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002121 wpa_hexdump_key(MSG_DEBUG, "RSN: AES-WRAP using KEK",
2122 sm->PTK.kek, sm->PTK.kek_len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002123 if (aes_wrap(sm->PTK.kek, sm->PTK.kek_len,
2124 (key_data_len - 8) / 8, buf, key_data)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002125 os_free(hdr);
Sunil Ravia04bd252022-05-02 22:54:18 -07002126 bin_clear_free(buf, key_data_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002127 return;
2128 }
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002129 wpa_hexdump(MSG_DEBUG,
2130 "RSN: Encrypted Key Data from AES-WRAP",
2131 key_data, key_data_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002132 WPA_PUT_BE16(key_mic + mic_len, key_data_len);
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002133#if !defined(CONFIG_NO_RC4) && !defined(CONFIG_FIPS)
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002134 } else if (sm->PTK.kek_len == 16) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002135 u8 ek[32];
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002136
2137 wpa_printf(MSG_DEBUG,
2138 "WPA: Encrypt Key Data using RC4");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002139 os_memcpy(key->key_iv,
2140 sm->group->Counter + WPA_NONCE_LEN - 16, 16);
2141 inc_byte_array(sm->group->Counter, WPA_NONCE_LEN);
2142 os_memcpy(ek, key->key_iv, 16);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002143 os_memcpy(ek + 16, sm->PTK.kek, sm->PTK.kek_len);
2144 os_memcpy(key_data, buf, key_data_len);
2145 rc4_skip(ek, 32, 256, key_data, key_data_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002146 WPA_PUT_BE16(key_mic + mic_len, key_data_len);
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002147#endif /* !(CONFIG_NO_RC4 || CONFIG_FIPS) */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002148 } else {
2149 os_free(hdr);
Sunil Ravia04bd252022-05-02 22:54:18 -07002150 bin_clear_free(buf, key_data_len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002151 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002152 }
Sunil Ravia04bd252022-05-02 22:54:18 -07002153 bin_clear_free(buf, key_data_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002154 }
2155
2156 if (key_info & WPA_KEY_INFO_MIC) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002157 if (!sm->PTK_valid || !mic_len) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07002158 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
2159 LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07002160 "PTK not valid when sending EAPOL-Key frame");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002161 os_free(hdr);
2162 return;
2163 }
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002164
Roshan Pius3a1667e2018-07-03 15:17:14 -07002165 if (wpa_eapol_key_mic(sm->PTK.kck, sm->PTK.kck_len,
2166 sm->wpa_key_mgmt, version,
2167 (u8 *) hdr, len, key_mic) < 0) {
2168 os_free(hdr);
2169 return;
2170 }
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002171#ifdef CONFIG_TESTING_OPTIONS
2172 if (!pairwise &&
Hai Shalomfdcde762020-04-02 11:19:20 -07002173 conf->corrupt_gtk_rekey_mic_probability > 0.0 &&
2174 drand48() < conf->corrupt_gtk_rekey_mic_probability) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07002175 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
2176 LOGGER_INFO,
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002177 "Corrupting group EAPOL-Key Key MIC");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002178 key_mic[0]++;
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002179 }
2180#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002181 }
2182
Hai Shalomfdcde762020-04-02 11:19:20 -07002183 wpa_auth_set_eapol(wpa_auth, sm->addr, WPA_EAPOL_inc_EapolFramesTx, 1);
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002184 wpa_hexdump(MSG_DEBUG, "Send EAPOL-Key msg", hdr, len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002185 wpa_auth_send_eapol(wpa_auth, sm->addr, (u8 *) hdr, len,
Kai Shie75b0652020-11-24 20:31:29 -08002186 sm->pairwise_set);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002187 os_free(hdr);
2188}
2189
2190
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002191static int wpa_auth_get_sta_count(struct wpa_authenticator *wpa_auth)
2192{
2193 if (!wpa_auth->cb->get_sta_count)
2194 return -1;
2195
2196 return wpa_auth->cb->get_sta_count(wpa_auth->cb_ctx);
2197}
2198
2199
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002200static void wpa_send_eapol(struct wpa_authenticator *wpa_auth,
2201 struct wpa_state_machine *sm, int key_info,
2202 const u8 *key_rsc, const u8 *nonce,
2203 const u8 *kde, size_t kde_len,
2204 int keyidx, int encr)
2205{
2206 int timeout_ms;
2207 int pairwise = key_info & WPA_KEY_INFO_KEY_TYPE;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002208 u32 ctr;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002209
Hai Shalomfdcde762020-04-02 11:19:20 -07002210 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002211 return;
2212
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002213 ctr = pairwise ? sm->TimeoutCtr : sm->GTimeoutCtr;
2214
2215#ifdef CONFIG_TESTING_OPTIONS
2216 /* When delay_eapol_tx is true, delay the EAPOL-Key transmission by
2217 * sending it only on the last attempt after all timeouts for the prior
2218 * skipped attemps. */
2219 if (wpa_auth->conf.delay_eapol_tx &&
2220 ctr != wpa_auth->conf.wpa_pairwise_update_count) {
2221 wpa_msg(sm->wpa_auth->conf.msg_ctx, MSG_INFO,
2222 "DELAY-EAPOL-TX-%d", ctr);
2223 goto skip_tx;
2224 }
2225#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002226 __wpa_send_eapol(wpa_auth, sm, key_info, key_rsc, nonce, kde, kde_len,
2227 keyidx, encr, 0);
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002228#ifdef CONFIG_TESTING_OPTIONS
2229skip_tx:
2230#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002231
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002232 if (ctr == 1 && wpa_auth->conf.tx_status) {
2233 if (pairwise)
2234 timeout_ms = eapol_key_timeout_first;
2235 else if (wpa_auth_get_sta_count(wpa_auth) > 100)
2236 timeout_ms = eapol_key_timeout_first_group * 2;
2237 else
2238 timeout_ms = eapol_key_timeout_first_group;
2239 } else {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002240 timeout_ms = eapol_key_timeout_subseq;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002241 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002242 if (wpa_auth->conf.wpa_disable_eapol_key_retries &&
2243 (!pairwise || (key_info & WPA_KEY_INFO_MIC)))
2244 timeout_ms = eapol_key_timeout_no_retrans;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002245 if (pairwise && ctr == 1 && !(key_info & WPA_KEY_INFO_MIC))
2246 sm->pending_1_of_4_timeout = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08002247#ifdef TEST_FUZZ
2248 timeout_ms = 1;
2249#endif /* TEST_FUZZ */
Kai Shie75b0652020-11-24 20:31:29 -08002250#ifdef CONFIG_TESTING_OPTIONS
2251 if(wpa_auth->conf.enable_eapol_large_timeout) {
2252 timeout_ms = 50 * 1000;
2253 }
2254#endif
Hai Shalomfdcde762020-04-02 11:19:20 -07002255 wpa_printf(MSG_DEBUG,
2256 "WPA: Use EAPOL-Key timeout of %u ms (retry counter %u)",
2257 timeout_ms, ctr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002258 eloop_register_timeout(timeout_ms / 1000, (timeout_ms % 1000) * 1000,
2259 wpa_send_eapol_timeout, wpa_auth, sm);
2260}
2261
2262
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002263static int wpa_verify_key_mic(int akmp, size_t pmk_len, struct wpa_ptk *PTK,
2264 u8 *data, size_t data_len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002265{
2266 struct ieee802_1x_hdr *hdr;
2267 struct wpa_eapol_key *key;
2268 u16 key_info;
2269 int ret = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002270 u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN], *mic_pos;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002271 size_t mic_len = wpa_mic_len(akmp, pmk_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002272
2273 if (data_len < sizeof(*hdr) + sizeof(*key))
2274 return -1;
2275
2276 hdr = (struct ieee802_1x_hdr *) data;
2277 key = (struct wpa_eapol_key *) (hdr + 1);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002278 mic_pos = (u8 *) (key + 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002279 key_info = WPA_GET_BE16(key->key_info);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002280 os_memcpy(mic, mic_pos, mic_len);
2281 os_memset(mic_pos, 0, mic_len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002282 if (wpa_eapol_key_mic(PTK->kck, PTK->kck_len, akmp,
2283 key_info & WPA_KEY_INFO_TYPE_MASK,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002284 data, data_len, mic_pos) ||
2285 os_memcmp_const(mic, mic_pos, mic_len) != 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002286 ret = -1;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002287 os_memcpy(mic_pos, mic, mic_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002288 return ret;
2289}
2290
2291
2292void wpa_remove_ptk(struct wpa_state_machine *sm)
2293{
Hai Shalome21d4e82020-04-29 16:34:06 -07002294 sm->PTK_valid = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002295 os_memset(&sm->PTK, 0, sizeof(sm->PTK));
Hai Shalom60840252021-02-19 19:02:11 -08002296
2297 wpa_auth_remove_ptksa(sm->wpa_auth, sm->addr, sm->pairwise);
2298
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002299 if (wpa_auth_set_key(sm->wpa_auth, 0, WPA_ALG_NONE, sm->addr, 0, NULL,
Hai Shalomfdcde762020-04-02 11:19:20 -07002300 0, KEY_FLAG_PAIRWISE))
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002301 wpa_printf(MSG_DEBUG,
2302 "RSN: PTK removal from the driver failed");
Hai Shalomfdcde762020-04-02 11:19:20 -07002303 if (sm->use_ext_key_id &&
2304 wpa_auth_set_key(sm->wpa_auth, 0, WPA_ALG_NONE, sm->addr, 1, NULL,
2305 0, KEY_FLAG_PAIRWISE))
2306 wpa_printf(MSG_DEBUG,
2307 "RSN: PTK Key ID 1 removal from the driver failed");
Hai Shalome21d4e82020-04-29 16:34:06 -07002308 sm->pairwise_set = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002309 eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm);
2310}
2311
2312
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002313int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002314{
2315 int remove_ptk = 1;
2316
Hai Shalomfdcde762020-04-02 11:19:20 -07002317 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002318 return -1;
2319
Sunil Raviaf8751c2023-03-29 11:35:17 -07002320 wpa_auth_vlogger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002321 "event %d notification", event);
2322
2323 switch (event) {
2324 case WPA_AUTH:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002325#ifdef CONFIG_MESH
2326 /* PTKs are derived through AMPE */
2327 if (wpa_auth_start_ampe(sm->wpa_auth, sm->addr)) {
2328 /* not mesh */
2329 break;
2330 }
2331 return 0;
2332#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002333 case WPA_ASSOC:
2334 break;
2335 case WPA_DEAUTH:
2336 case WPA_DISASSOC:
Hai Shalome21d4e82020-04-29 16:34:06 -07002337 sm->DeauthenticationRequest = true;
Hai Shalom1dc4d202019-04-29 16:22:27 -07002338 os_memset(sm->PMK, 0, sizeof(sm->PMK));
2339 sm->pmk_len = 0;
Sunil Ravia04bd252022-05-02 22:54:18 -07002340#ifdef CONFIG_IEEE80211R_AP
Hai Shalom1dc4d202019-04-29 16:22:27 -07002341 os_memset(sm->xxkey, 0, sizeof(sm->xxkey));
2342 sm->xxkey_len = 0;
Hai Shalom81f62d82019-07-22 12:10:00 -07002343 os_memset(sm->pmk_r1, 0, sizeof(sm->pmk_r1));
2344 sm->pmk_r1_len = 0;
Hai Shalom1dc4d202019-04-29 16:22:27 -07002345#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002346 break;
2347 case WPA_REAUTH:
2348 case WPA_REAUTH_EAPOL:
2349 if (!sm->started) {
2350 /*
2351 * When using WPS, we may end up here if the STA
2352 * manages to re-associate without the previous STA
2353 * entry getting removed. Consequently, we need to make
2354 * sure that the WPA state machines gets initialized
2355 * properly at this point.
2356 */
Hai Shalomfdcde762020-04-02 11:19:20 -07002357 wpa_printf(MSG_DEBUG,
2358 "WPA state machine had not been started - initialize now");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002359 sm->started = 1;
Hai Shalome21d4e82020-04-29 16:34:06 -07002360 sm->Init = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002361 if (wpa_sm_step(sm) == 1)
2362 return 1; /* should not really happen */
Hai Shalome21d4e82020-04-29 16:34:06 -07002363 sm->Init = false;
2364 sm->AuthenticationRequest = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002365 break;
2366 }
Hai Shalomfdcde762020-04-02 11:19:20 -07002367
Sunil Ravia04bd252022-05-02 22:54:18 -07002368 if (sm->ptkstart_without_success > 3) {
2369 wpa_printf(MSG_INFO,
2370 "WPA: Multiple EAP reauth attempts without 4-way handshake completion, disconnect "
2371 MACSTR, MAC2STR(sm->addr));
2372 sm->Disconnect = true;
2373 break;
2374 }
2375
Hai Shalomfdcde762020-04-02 11:19:20 -07002376 if (!sm->use_ext_key_id &&
2377 sm->wpa_auth->conf.wpa_deny_ptk0_rekey) {
2378 wpa_printf(MSG_INFO,
2379 "WPA: PTK0 rekey not allowed, disconnect "
Sunil Raviaf8751c2023-03-29 11:35:17 -07002380 MACSTR, MAC2STR(wpa_auth_get_spa(sm)));
Hai Shalome21d4e82020-04-29 16:34:06 -07002381 sm->Disconnect = true;
Hai Shalomfdcde762020-04-02 11:19:20 -07002382 /* Try to encourage the STA to reconnect */
2383 sm->disconnect_reason =
2384 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA;
2385 break;
2386 }
2387
2388 if (sm->use_ext_key_id)
2389 sm->keyidx_active ^= 1; /* flip Key ID */
2390
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002391 if (sm->GUpdateStationKeys) {
2392 /*
2393 * Reauthentication cancels the pending group key
2394 * update for this STA.
2395 */
Sunil Ravi7f769292024-07-23 22:21:32 +00002396 wpa_gkeydone_sta(sm);
Hai Shalome21d4e82020-04-29 16:34:06 -07002397 sm->PtkGroupInit = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002398 }
Hai Shalome21d4e82020-04-29 16:34:06 -07002399 sm->ReAuthenticationRequest = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002400 break;
2401 case WPA_ASSOC_FT:
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002402#ifdef CONFIG_IEEE80211R_AP
Hai Shalomfdcde762020-04-02 11:19:20 -07002403 wpa_printf(MSG_DEBUG,
2404 "FT: Retry PTK configuration after association");
Hai Shalomb755a2a2020-04-23 21:49:02 -07002405 wpa_ft_install_ptk(sm, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002406
2407 /* Using FT protocol, not WPA auth state machine */
2408 sm->ft_completed = 1;
Hai Shalom81f62d82019-07-22 12:10:00 -07002409 wpa_auth_set_ptk_rekey_timer(sm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002410 return 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002411#else /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002412 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002413#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002414 case WPA_ASSOC_FILS:
2415#ifdef CONFIG_FILS
2416 wpa_printf(MSG_DEBUG,
2417 "FILS: TK configuration after association");
2418 fils_set_tk(sm);
2419 sm->fils_completed = 1;
2420 return 0;
2421#else /* CONFIG_FILS */
2422 break;
2423#endif /* CONFIG_FILS */
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02002424 case WPA_DRV_STA_REMOVED:
Hai Shalome21d4e82020-04-29 16:34:06 -07002425 sm->tk_already_set = false;
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02002426 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002427 }
2428
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002429#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002430 sm->ft_completed = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002431#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002432
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002433 if (sm->mgmt_frame_prot && event == WPA_AUTH)
2434 remove_ptk = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002435#ifdef CONFIG_FILS
2436 if (wpa_key_mgmt_fils(sm->wpa_key_mgmt) &&
2437 (event == WPA_AUTH || event == WPA_ASSOC))
2438 remove_ptk = 0;
2439#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002440
2441 if (remove_ptk) {
Hai Shalome21d4e82020-04-29 16:34:06 -07002442 sm->PTK_valid = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002443 os_memset(&sm->PTK, 0, sizeof(sm->PTK));
2444
2445 if (event != WPA_REAUTH_EAPOL)
2446 wpa_remove_ptk(sm);
2447 }
2448
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002449 if (sm->in_step_loop) {
2450 /*
2451 * wpa_sm_step() is already running - avoid recursive call to
2452 * it by making the existing loop process the new update.
2453 */
Hai Shalome21d4e82020-04-29 16:34:06 -07002454 sm->changed = true;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002455 return 0;
2456 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002457 return wpa_sm_step(sm);
2458}
2459
2460
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002461SM_STATE(WPA_PTK, INITIALIZE)
2462{
2463 SM_ENTRY_MA(WPA_PTK, INITIALIZE, wpa_ptk);
2464 if (sm->Init) {
2465 /* Init flag is not cleared here, so avoid busy
2466 * loop by claiming nothing changed. */
Hai Shalome21d4e82020-04-29 16:34:06 -07002467 sm->changed = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002468 }
2469
2470 sm->keycount = 0;
2471 if (sm->GUpdateStationKeys)
Sunil Ravi7f769292024-07-23 22:21:32 +00002472 wpa_gkeydone_sta(sm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002473 if (sm->wpa == WPA_VERSION_WPA)
Hai Shalome21d4e82020-04-29 16:34:06 -07002474 sm->PInitAKeys = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002475 if (1 /* Unicast cipher supported AND (ESS OR ((IBSS or WDS) and
2476 * Local AA > Remote AA)) */) {
Hai Shalome21d4e82020-04-29 16:34:06 -07002477 sm->Pair = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002478 }
2479 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 0);
2480 wpa_remove_ptk(sm);
2481 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid, 0);
2482 sm->TimeoutCtr = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002483 if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
2484 sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP ||
2485 sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002486 wpa_auth_set_eapol(sm->wpa_auth, sm->addr,
2487 WPA_EAPOL_authorized, 0);
2488 }
2489}
2490
2491
2492SM_STATE(WPA_PTK, DISCONNECT)
2493{
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002494 u16 reason = sm->disconnect_reason;
2495
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002496 SM_ENTRY_MA(WPA_PTK, DISCONNECT, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07002497 sm->Disconnect = false;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002498 sm->disconnect_reason = 0;
2499 if (!reason)
2500 reason = WLAN_REASON_PREV_AUTH_NOT_VALID;
2501 wpa_sta_disconnect(sm->wpa_auth, sm->addr, reason);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002502}
2503
2504
2505SM_STATE(WPA_PTK, DISCONNECTED)
2506{
2507 SM_ENTRY_MA(WPA_PTK, DISCONNECTED, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07002508 sm->DeauthenticationRequest = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002509}
2510
2511
2512SM_STATE(WPA_PTK, AUTHENTICATION)
2513{
2514 SM_ENTRY_MA(WPA_PTK, AUTHENTICATION, wpa_ptk);
2515 os_memset(&sm->PTK, 0, sizeof(sm->PTK));
Hai Shalome21d4e82020-04-29 16:34:06 -07002516 sm->PTK_valid = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002517 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portControl_Auto,
2518 1);
2519 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 1);
Hai Shalome21d4e82020-04-29 16:34:06 -07002520 sm->AuthenticationRequest = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002521}
2522
2523
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002524static void wpa_group_ensure_init(struct wpa_authenticator *wpa_auth,
2525 struct wpa_group *group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002526{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002527 if (group->first_sta_seen)
2528 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002529 /*
2530 * System has run bit further than at the time hostapd was started
2531 * potentially very early during boot up. This provides better chances
2532 * of collecting more randomness on embedded systems. Re-initialize the
2533 * GMK and Counter here to improve their strength if there was not
2534 * enough entropy available immediately after system startup.
2535 */
Hai Shalomfdcde762020-04-02 11:19:20 -07002536 wpa_printf(MSG_DEBUG,
2537 "WPA: Re-initialize GMK/Counter on first station");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002538 if (random_pool_ready() != 1) {
Hai Shalomfdcde762020-04-02 11:19:20 -07002539 wpa_printf(MSG_INFO,
2540 "WPA: Not enough entropy in random pool to proceed - reject first 4-way handshake");
Hai Shalome21d4e82020-04-29 16:34:06 -07002541 group->reject_4way_hs_for_entropy = true;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002542 } else {
Hai Shalome21d4e82020-04-29 16:34:06 -07002543 group->first_sta_seen = true;
2544 group->reject_4way_hs_for_entropy = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002545 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002546
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002547 if (wpa_group_init_gmk_and_counter(wpa_auth, group) < 0 ||
2548 wpa_gtk_update(wpa_auth, group) < 0 ||
2549 wpa_group_config_group_keys(wpa_auth, group) < 0) {
2550 wpa_printf(MSG_INFO, "WPA: GMK/GTK setup failed");
Hai Shalome21d4e82020-04-29 16:34:06 -07002551 group->first_sta_seen = false;
2552 group->reject_4way_hs_for_entropy = true;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002553 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002554}
2555
2556
2557SM_STATE(WPA_PTK, AUTHENTICATION2)
2558{
2559 SM_ENTRY_MA(WPA_PTK, AUTHENTICATION2, wpa_ptk);
2560
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002561 wpa_group_ensure_init(sm->wpa_auth, sm->group);
Hai Shalome21d4e82020-04-29 16:34:06 -07002562 sm->ReAuthenticationRequest = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002563
Dmitry Shmidt04949592012-07-19 12:16:46 -07002564 /*
2565 * Definition of ANonce selection in IEEE Std 802.11i-2004 is somewhat
2566 * ambiguous. The Authenticator state machine uses a counter that is
2567 * incremented by one for each 4-way handshake. However, the security
2568 * analysis of 4-way handshake points out that unpredictable nonces
2569 * help in preventing precomputation attacks. Instead of the state
2570 * machine definition, use an unpredictable nonce value here to provide
2571 * stronger protection against potential precomputation attacks.
2572 */
2573 if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) {
Hai Shalomfdcde762020-04-02 11:19:20 -07002574 wpa_printf(MSG_ERROR,
2575 "WPA: Failed to get random data for ANonce.");
Hai Shalome21d4e82020-04-29 16:34:06 -07002576 sm->Disconnect = true;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002577 return;
2578 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002579 wpa_hexdump(MSG_DEBUG, "WPA: Assign ANonce", sm->ANonce,
2580 WPA_NONCE_LEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002581 /* IEEE 802.11i does not clear TimeoutCtr here, but this is more
2582 * logical place than INITIALIZE since AUTHENTICATION2 can be
2583 * re-entered on ReAuthenticationRequest without going through
2584 * INITIALIZE. */
2585 sm->TimeoutCtr = 0;
2586}
2587
2588
Jouni Malinen1420a892017-10-01 12:32:57 +03002589static int wpa_auth_sm_ptk_update(struct wpa_state_machine *sm)
2590{
2591 if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) {
2592 wpa_printf(MSG_ERROR,
2593 "WPA: Failed to get random data for ANonce");
Hai Shalome21d4e82020-04-29 16:34:06 -07002594 sm->Disconnect = true;
Jouni Malinen1420a892017-10-01 12:32:57 +03002595 return -1;
2596 }
2597 wpa_hexdump(MSG_DEBUG, "WPA: Assign new ANonce", sm->ANonce,
2598 WPA_NONCE_LEN);
2599 sm->TimeoutCtr = 0;
2600 return 0;
2601}
2602
2603
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002604SM_STATE(WPA_PTK, INITPMK)
2605{
2606 u8 msk[2 * PMK_LEN];
2607 size_t len = 2 * PMK_LEN;
2608
2609 SM_ENTRY_MA(WPA_PTK, INITPMK, wpa_ptk);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002610#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002611 sm->xxkey_len = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002612#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002613 if (sm->pmksa) {
2614 wpa_printf(MSG_DEBUG, "WPA: PMK from PMKSA cache");
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002615 os_memcpy(sm->PMK, sm->pmksa->pmk, sm->pmksa->pmk_len);
2616 sm->pmk_len = sm->pmksa->pmk_len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002617#ifdef CONFIG_DPP
2618 } else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP) {
2619 wpa_printf(MSG_DEBUG,
2620 "DPP: No PMKSA cache entry for STA - reject connection");
Hai Shalome21d4e82020-04-29 16:34:06 -07002621 sm->Disconnect = true;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002622 sm->disconnect_reason = WLAN_REASON_INVALID_PMKID;
2623 return;
2624#endif /* CONFIG_DPP */
Sunil Raviaf8751c2023-03-29 11:35:17 -07002625 } else if (wpa_auth_get_msk(sm->wpa_auth, wpa_auth_get_spa(sm),
2626 msk, &len) == 0) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002627 unsigned int pmk_len;
2628
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002629 if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002630 pmk_len = PMK_LEN_SUITE_B_192;
2631 else
2632 pmk_len = PMK_LEN;
Hai Shalomfdcde762020-04-02 11:19:20 -07002633 wpa_printf(MSG_DEBUG,
2634 "WPA: PMK from EAPOL state machine (MSK len=%zu PMK len=%u)",
2635 len, pmk_len);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002636 if (len < pmk_len) {
2637 wpa_printf(MSG_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07002638 "WPA: MSK not long enough (%zu) to create PMK (%u)",
2639 len, pmk_len);
Hai Shalome21d4e82020-04-29 16:34:06 -07002640 sm->Disconnect = true;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002641 return;
2642 }
2643 os_memcpy(sm->PMK, msk, pmk_len);
2644 sm->pmk_len = pmk_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002645#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002646 if (len >= 2 * PMK_LEN) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002647 if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) {
2648 os_memcpy(sm->xxkey, msk, SHA384_MAC_LEN);
2649 sm->xxkey_len = SHA384_MAC_LEN;
2650 } else {
2651 os_memcpy(sm->xxkey, msk + PMK_LEN, PMK_LEN);
2652 sm->xxkey_len = PMK_LEN;
2653 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002654 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002655#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002656 } else {
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002657 wpa_printf(MSG_DEBUG, "WPA: Could not get PMK, get_msk: %p",
Paul Stewart092955c2017-02-06 09:13:09 -08002658 sm->wpa_auth->cb->get_msk);
Hai Shalome21d4e82020-04-29 16:34:06 -07002659 sm->Disconnect = true;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002660 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002661 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002662 forced_memzero(msk, sizeof(msk));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002663
2664 sm->req_replay_counter_used = 0;
Hai Shalome21d4e82020-04-29 16:34:06 -07002665 /* IEEE 802.11i does not set keyRun to false, but not doing this
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002666 * will break reauthentication since EAPOL state machines may not be
2667 * get into AUTHENTICATING state that clears keyRun before WPA state
2668 * machine enters AUTHENTICATION2 state and goes immediately to INITPMK
2669 * state and takes PMK from the previously used AAA Key. This will
2670 * eventually fail in 4-Way Handshake because Supplicant uses PMK
Hai Shalome21d4e82020-04-29 16:34:06 -07002671 * derived from the new AAA Key. Setting keyRun = false here seems to
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002672 * be good workaround for this issue. */
Hai Shalome21d4e82020-04-29 16:34:06 -07002673 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyRun, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002674}
2675
2676
2677SM_STATE(WPA_PTK, INITPSK)
2678{
2679 const u8 *psk;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002680 size_t psk_len;
2681
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002682 SM_ENTRY_MA(WPA_PTK, INITPSK, wpa_ptk);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002683 psk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr, NULL,
Hai Shalom021b0b52019-04-10 11:17:58 -07002684 &psk_len, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002685 if (psk) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002686 os_memcpy(sm->PMK, psk, psk_len);
2687 sm->pmk_len = psk_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002688#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002689 sm->xxkey_len = PMK_LEN;
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002690#ifdef CONFIG_SAE
2691 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_SAE_EXT_KEY &&
2692 (psk_len == SHA512_MAC_LEN || psk_len == SHA384_MAC_LEN ||
2693 psk_len == SHA256_MAC_LEN))
2694 sm->xxkey_len = psk_len;
2695#endif /* CONFIG_SAE */
2696 os_memcpy(sm->xxkey, psk, sm->xxkey_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002697#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002698 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002699#ifdef CONFIG_SAE
2700 if (wpa_auth_uses_sae(sm) && sm->pmksa) {
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002701 wpa_printf(MSG_DEBUG, "SAE: PMK from PMKSA cache (len=%zu)",
2702 sm->pmksa->pmk_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002703 os_memcpy(sm->PMK, sm->pmksa->pmk, sm->pmksa->pmk_len);
2704 sm->pmk_len = sm->pmksa->pmk_len;
Hai Shalom021b0b52019-04-10 11:17:58 -07002705#ifdef CONFIG_IEEE80211R_AP
2706 os_memcpy(sm->xxkey, sm->pmksa->pmk, sm->pmksa->pmk_len);
2707 sm->xxkey_len = sm->pmksa->pmk_len;
2708#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002709 }
2710#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002711 sm->req_replay_counter_used = 0;
2712}
2713
2714
2715SM_STATE(WPA_PTK, PTKSTART)
2716{
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002717 u8 *buf;
2718 size_t buf_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002719 u8 *pmkid = NULL;
2720 size_t kde_len = 0;
Sunil8cd6f4d2022-06-28 18:40:46 +00002721 u16 key_info;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002722#ifdef CONFIG_TESTING_OPTIONS
2723 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
2724#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002725
2726 SM_ENTRY_MA(WPA_PTK, PTKSTART, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07002727 sm->PTKRequest = false;
2728 sm->TimeoutEvt = false;
2729 sm->alt_snonce_valid = false;
Sunil Ravia04bd252022-05-02 22:54:18 -07002730 sm->ptkstart_without_success++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002731
2732 sm->TimeoutCtr++;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002733 if (sm->TimeoutCtr > sm->wpa_auth->conf.wpa_pairwise_update_count) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002734 /* No point in sending the EAPOL-Key - we will disconnect
2735 * immediately following this. */
2736 return;
2737 }
2738
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002739#ifdef CONFIG_IEEE80211BE
2740 if (sm->mld_assoc_link_id >= 0)
2741 buf_len += 2 + RSN_SELECTOR_LEN + ETH_ALEN;
2742#endif /* CONFIG_IEEE80211BE */
2743#ifdef CONFIG_TESTING_OPTIONS
2744 if (conf->eapol_m1_elements)
2745 buf_len += wpabuf_len(conf->eapol_m1_elements);
2746#endif /* CONFIG_TESTING_OPTIONS */
2747
2748 buf = os_zalloc(buf_len);
2749 if (!buf)
2750 return;
2751
Sunil Raviaf8751c2023-03-29 11:35:17 -07002752 wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002753 "sending 1/4 msg of 4-Way Handshake");
2754 /*
Hai Shalomce48b4a2018-09-05 11:41:35 -07002755 * For infrastructure BSS cases, it is better for the AP not to include
2756 * the PMKID KDE in EAPOL-Key msg 1/4 since it could be used to initiate
2757 * offline search for the passphrase/PSK without having to be able to
2758 * capture a 4-way handshake from a STA that has access to the network.
2759 *
2760 * For IBSS cases, addition of PMKID KDE could be considered even with
2761 * WPA2-PSK cases that use multiple PSKs, but only if there is a single
2762 * possible PSK for this STA. However, this should not be done unless
2763 * there is support for using that information on the supplicant side.
2764 * The concern about exposing PMKID unnecessarily in infrastructure BSS
2765 * cases would also apply here, but at least in the IBSS case, this
2766 * would cover a potential real use case.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002767 */
2768 if (sm->wpa == WPA_VERSION_WPA2 &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002769 (wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) ||
2770 (sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE && sm->pmksa) ||
2771 wpa_key_mgmt_sae(sm->wpa_key_mgmt)) &&
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002772 sm->wpa_key_mgmt != WPA_KEY_MGMT_OSEN) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002773 pmkid = buf;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002774 kde_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002775 pmkid[0] = WLAN_EID_VENDOR_SPECIFIC;
2776 pmkid[1] = RSN_SELECTOR_LEN + PMKID_LEN;
2777 RSN_SELECTOR_PUT(&pmkid[2], RSN_KEY_DATA_PMKID);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002778 if (sm->pmksa) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002779 wpa_hexdump(MSG_DEBUG,
2780 "RSN: Message 1/4 PMKID from PMKSA entry",
2781 sm->pmksa->pmkid, PMKID_LEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002782 os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN],
2783 sm->pmksa->pmkid, PMKID_LEN);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002784 } else if (wpa_key_mgmt_suite_b(sm->wpa_key_mgmt)) {
2785 /* No KCK available to derive PMKID */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002786 wpa_printf(MSG_DEBUG,
2787 "RSN: No KCK available to derive PMKID for message 1/4");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002788 pmkid = NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -07002789#ifdef CONFIG_FILS
2790 } else if (wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
2791 if (sm->pmkid_set) {
2792 wpa_hexdump(MSG_DEBUG,
2793 "RSN: Message 1/4 PMKID from FILS/ERP",
2794 sm->pmkid, PMKID_LEN);
2795 os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN],
2796 sm->pmkid, PMKID_LEN);
2797 } else {
2798 /* No PMKID available */
2799 wpa_printf(MSG_DEBUG,
2800 "RSN: No FILS/ERP PMKID available for message 1/4");
2801 pmkid = NULL;
2802 }
2803#endif /* CONFIG_FILS */
2804#ifdef CONFIG_IEEE80211R_AP
2805 } else if (wpa_key_mgmt_ft(sm->wpa_key_mgmt) &&
2806 sm->ft_completed) {
2807 wpa_printf(MSG_DEBUG,
2808 "FT: No PMKID in message 1/4 when using FT protocol");
2809 pmkid = NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -07002810#endif /* CONFIG_IEEE80211R_AP */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002811#ifdef CONFIG_SAE
2812 } else if (wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
2813 if (sm->pmkid_set) {
2814 wpa_hexdump(MSG_DEBUG,
2815 "RSN: Message 1/4 PMKID from SAE",
2816 sm->pmkid, PMKID_LEN);
2817 os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN],
2818 sm->pmkid, PMKID_LEN);
2819 } else {
2820 /* No PMKID available */
2821 wpa_printf(MSG_DEBUG,
2822 "RSN: No SAE PMKID available for message 1/4");
2823 pmkid = NULL;
2824 }
2825#endif /* CONFIG_SAE */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002826 } else {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002827 /*
2828 * Calculate PMKID since no PMKSA cache entry was
2829 * available with pre-calculated PMKID.
2830 */
Sunil Raviaf8751c2023-03-29 11:35:17 -07002831 rsn_pmkid(sm->PMK, sm->pmk_len,
2832 wpa_auth_get_aa(sm),
2833 wpa_auth_get_spa(sm),
2834 &pmkid[2 + RSN_SELECTOR_LEN],
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002835 sm->wpa_key_mgmt);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002836 wpa_hexdump(MSG_DEBUG,
2837 "RSN: Message 1/4 PMKID derived from PMK",
2838 &pmkid[2 + RSN_SELECTOR_LEN], PMKID_LEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002839 }
2840 }
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002841 if (!pmkid)
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002842 kde_len = 0;
2843
2844#ifdef CONFIG_IEEE80211BE
2845 if (sm->mld_assoc_link_id >= 0) {
2846 wpa_printf(MSG_DEBUG,
2847 "RSN: MLD: Add MAC Address KDE: kde_len=%zu",
2848 kde_len);
2849 wpa_add_kde(buf + kde_len, RSN_KEY_DATA_MAC_ADDR,
Sunil Ravi7f769292024-07-23 22:21:32 +00002850 sm->wpa_auth->mld_addr, ETH_ALEN, NULL, 0);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002851 kde_len += 2 + RSN_SELECTOR_LEN + ETH_ALEN;
2852 }
2853#endif /* CONFIG_IEEE80211BE */
2854
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002855#ifdef CONFIG_TESTING_OPTIONS
2856 if (conf->eapol_m1_elements) {
2857 os_memcpy(buf + kde_len, wpabuf_head(conf->eapol_m1_elements),
2858 wpabuf_len(conf->eapol_m1_elements));
2859 kde_len += wpabuf_len(conf->eapol_m1_elements);
2860 }
2861#endif /* CONFIG_TESTING_OPTIONS */
2862
Sunil8cd6f4d2022-06-28 18:40:46 +00002863 key_info = WPA_KEY_INFO_ACK | WPA_KEY_INFO_KEY_TYPE;
2864 if (sm->pairwise_set && sm->wpa != WPA_VERSION_WPA)
2865 key_info |= WPA_KEY_INFO_SECURE;
2866 wpa_send_eapol(sm->wpa_auth, sm, key_info, NULL,
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002867 sm->ANonce, kde_len ? buf : NULL, kde_len, 0, 0);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002868 os_free(buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002869}
2870
2871
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002872static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002873 const u8 *pmk, unsigned int pmk_len,
Sunil Raviaf8751c2023-03-29 11:35:17 -07002874 struct wpa_ptk *ptk, int force_sha256,
2875 u8 *pmk_r0, u8 *pmk_r1, u8 *pmk_r0_name,
Sunil Ravi7f769292024-07-23 22:21:32 +00002876 size_t *key_len, bool no_kdk)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002877{
Hai Shalom021b0b52019-04-10 11:17:58 -07002878 const u8 *z = NULL;
Hai Shalom60840252021-02-19 19:02:11 -08002879 size_t z_len = 0, kdk_len;
Hai Shalomfdcde762020-04-02 11:19:20 -07002880 int akmp;
Sunil Ravi89eba102022-09-13 21:04:37 -07002881 int ret;
Hai Shalom021b0b52019-04-10 11:17:58 -07002882
Hai Shalom60840252021-02-19 19:02:11 -08002883 if (sm->wpa_auth->conf.force_kdk_derivation ||
Sunil Ravi7f769292024-07-23 22:21:32 +00002884 (!no_kdk && sm->wpa_auth->conf.secure_ltf &&
Hai Shaloma20dcd72022-02-04 13:43:00 -08002885 ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
Hai Shalom60840252021-02-19 19:02:11 -08002886 kdk_len = WPA_KDK_MAX_LEN;
2887 else
2888 kdk_len = 0;
2889
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002890#ifdef CONFIG_IEEE80211R_AP
Hai Shalom81f62d82019-07-22 12:10:00 -07002891 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
2892 if (sm->ft_completed) {
2893 u8 ptk_name[WPA_PMK_NAME_LEN];
2894
Sunil Ravi89eba102022-09-13 21:04:37 -07002895 ret = wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->pmk_r1_len,
2896 sm->SNonce, sm->ANonce,
Sunil Raviaf8751c2023-03-29 11:35:17 -07002897 wpa_auth_get_spa(sm),
2898 wpa_auth_get_aa(sm),
Sunil Ravi89eba102022-09-13 21:04:37 -07002899 sm->pmk_r1_name, ptk,
2900 ptk_name, sm->wpa_key_mgmt,
2901 sm->pairwise, kdk_len);
2902 } else {
Sunil Raviaf8751c2023-03-29 11:35:17 -07002903 ret = wpa_auth_derive_ptk_ft(sm, ptk, pmk_r0, pmk_r1,
2904 pmk_r0_name, key_len,
2905 kdk_len);
Hai Shalom81f62d82019-07-22 12:10:00 -07002906 }
Sunil Ravi89eba102022-09-13 21:04:37 -07002907 if (ret) {
2908 wpa_printf(MSG_ERROR, "FT: PTK derivation failed");
2909 return ret;
2910 }
2911
2912#ifdef CONFIG_PASN
Sunil Ravi7f769292024-07-23 22:21:32 +00002913 if (!no_kdk && sm->wpa_auth->conf.secure_ltf &&
Sunil Ravi89eba102022-09-13 21:04:37 -07002914 ieee802_11_rsnx_capab(sm->rsnxe,
2915 WLAN_RSNX_CAPAB_SECURE_LTF)) {
2916 ret = wpa_ltf_keyseed(ptk, sm->wpa_key_mgmt,
2917 sm->pairwise);
2918 if (ret) {
2919 wpa_printf(MSG_ERROR,
2920 "FT: LTF keyseed derivation failed");
2921 }
2922 }
2923#endif /* CONFIG_PASN */
2924 return ret;
Hai Shalom81f62d82019-07-22 12:10:00 -07002925 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002926#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002927
Hai Shalom021b0b52019-04-10 11:17:58 -07002928#ifdef CONFIG_DPP2
2929 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP && sm->dpp_z) {
2930 z = wpabuf_head(sm->dpp_z);
2931 z_len = wpabuf_len(sm->dpp_z);
2932 }
2933#endif /* CONFIG_DPP2 */
2934
Hai Shalomfdcde762020-04-02 11:19:20 -07002935 akmp = sm->wpa_key_mgmt;
2936 if (force_sha256)
2937 akmp |= WPA_KEY_MGMT_PSK_SHA256;
Sunil Ravi89eba102022-09-13 21:04:37 -07002938 ret = wpa_pmk_to_ptk(pmk, pmk_len, "Pairwise key expansion",
Sunil Raviaf8751c2023-03-29 11:35:17 -07002939 wpa_auth_get_aa(sm), wpa_auth_get_spa(sm),
2940 sm->ANonce, snonce, ptk, akmp,
2941 sm->pairwise, z, z_len, kdk_len);
Sunil Ravi89eba102022-09-13 21:04:37 -07002942 if (ret) {
2943 wpa_printf(MSG_DEBUG,
2944 "WPA: PTK derivation failed");
2945 return ret;
2946 }
2947
2948#ifdef CONFIG_PASN
Sunil Ravi7f769292024-07-23 22:21:32 +00002949 if (!no_kdk && sm->wpa_auth->conf.secure_ltf &&
Sunil Ravi89eba102022-09-13 21:04:37 -07002950 ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)) {
2951 ret = wpa_ltf_keyseed(ptk, sm->wpa_key_mgmt, sm->pairwise);
2952 if (ret) {
2953 wpa_printf(MSG_DEBUG,
2954 "WPA: LTF keyseed derivation failed");
2955 }
2956 }
2957#endif /* CONFIG_PASN */
2958 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002959}
2960
2961
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002962#ifdef CONFIG_FILS
2963
2964int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002965 size_t pmk_len, const u8 *snonce, const u8 *anonce,
2966 const u8 *dhss, size_t dhss_len,
2967 struct wpabuf *g_sta, struct wpabuf *g_ap)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002968{
2969 u8 ick[FILS_ICK_MAX_LEN];
2970 size_t ick_len;
2971 int res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002972 u8 fils_ft[FILS_FT_MAX_LEN];
Hai Shalom60840252021-02-19 19:02:11 -08002973 size_t fils_ft_len = 0, kdk_len;
2974
2975 if (sm->wpa_auth->conf.force_kdk_derivation ||
2976 (sm->wpa_auth->conf.secure_ltf &&
Hai Shaloma20dcd72022-02-04 13:43:00 -08002977 ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
Hai Shalom60840252021-02-19 19:02:11 -08002978 kdk_len = WPA_KDK_MAX_LEN;
2979 else
2980 kdk_len = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002981
Sunil Raviaf8751c2023-03-29 11:35:17 -07002982 res = fils_pmk_to_ptk(pmk, pmk_len, wpa_auth_get_spa(sm),
2983 wpa_auth_get_aa(sm),
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002984 snonce, anonce, dhss, dhss_len,
2985 &sm->PTK, ick, &ick_len,
2986 sm->wpa_key_mgmt, sm->pairwise,
Hai Shalom60840252021-02-19 19:02:11 -08002987 fils_ft, &fils_ft_len, kdk_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002988 if (res < 0)
2989 return res;
Sunil Ravi89eba102022-09-13 21:04:37 -07002990
2991#ifdef CONFIG_PASN
2992 if (sm->wpa_auth->conf.secure_ltf &&
2993 ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)) {
2994 res = wpa_ltf_keyseed(&sm->PTK, sm->wpa_key_mgmt, sm->pairwise);
2995 if (res) {
2996 wpa_printf(MSG_ERROR,
2997 "FILS: LTF keyseed derivation failed");
2998 return res;
2999 }
3000 }
3001#endif /* CONFIG_PASN */
3002
Hai Shalome21d4e82020-04-29 16:34:06 -07003003 sm->PTK_valid = true;
3004 sm->tk_already_set = false;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003005
3006#ifdef CONFIG_IEEE80211R_AP
3007 if (fils_ft_len) {
3008 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
3009 struct wpa_auth_config *conf = &wpa_auth->conf;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003010 u8 pmk_r0[PMK_LEN_MAX], pmk_r0_name[WPA_PMK_NAME_LEN];
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003011
3012 if (wpa_derive_pmk_r0(fils_ft, fils_ft_len,
3013 conf->ssid, conf->ssid_len,
3014 conf->mobility_domain,
3015 conf->r0_key_holder,
3016 conf->r0_key_holder_len,
Sunil Raviaf8751c2023-03-29 11:35:17 -07003017 wpa_auth_get_spa(sm), pmk_r0, pmk_r0_name,
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00003018 sm->wpa_key_mgmt) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003019 return -1;
3020
Roshan Pius3a1667e2018-07-03 15:17:14 -07003021 wpa_ft_store_pmk_fils(sm, pmk_r0, pmk_r0_name);
Hai Shalom81f62d82019-07-22 12:10:00 -07003022 forced_memzero(fils_ft, sizeof(fils_ft));
Hai Shalom021b0b52019-04-10 11:17:58 -07003023
3024 res = wpa_derive_pmk_r1_name(pmk_r0_name, conf->r1_key_holder,
Sunil Raviaf8751c2023-03-29 11:35:17 -07003025 wpa_auth_get_spa(sm),
3026 sm->pmk_r1_name,
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00003027 fils_ft_len);
Hai Shalom81f62d82019-07-22 12:10:00 -07003028 forced_memzero(pmk_r0, PMK_LEN_MAX);
Hai Shalom021b0b52019-04-10 11:17:58 -07003029 if (res < 0)
3030 return -1;
3031 wpa_hexdump(MSG_DEBUG, "FILS+FT: PMKR1Name", sm->pmk_r1_name,
3032 WPA_PMK_NAME_LEN);
3033 sm->pmk_r1_name_valid = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003034 }
3035#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003036
3037 res = fils_key_auth_sk(ick, ick_len, snonce, anonce,
Sunil Raviaf8751c2023-03-29 11:35:17 -07003038 wpa_auth_get_spa(sm),
3039 wpa_auth_get_aa(sm),
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003040 g_sta ? wpabuf_head(g_sta) : NULL,
3041 g_sta ? wpabuf_len(g_sta) : 0,
3042 g_ap ? wpabuf_head(g_ap) : NULL,
3043 g_ap ? wpabuf_len(g_ap) : 0,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003044 sm->wpa_key_mgmt, sm->fils_key_auth_sta,
3045 sm->fils_key_auth_ap,
3046 &sm->fils_key_auth_len);
Hai Shalom81f62d82019-07-22 12:10:00 -07003047 forced_memzero(ick, sizeof(ick));
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003048
3049 /* Store nonces for (Re)Association Request/Response frame processing */
3050 os_memcpy(sm->SNonce, snonce, FILS_NONCE_LEN);
3051 os_memcpy(sm->ANonce, anonce, FILS_NONCE_LEN);
3052
3053 return res;
3054}
3055
3056
3057static int wpa_aead_decrypt(struct wpa_state_machine *sm, struct wpa_ptk *ptk,
3058 u8 *buf, size_t buf_len, u16 *_key_data_len)
3059{
3060 struct ieee802_1x_hdr *hdr;
3061 struct wpa_eapol_key *key;
3062 u8 *pos;
3063 u16 key_data_len;
3064 u8 *tmp;
3065 const u8 *aad[1];
3066 size_t aad_len[1];
3067
3068 hdr = (struct ieee802_1x_hdr *) buf;
3069 key = (struct wpa_eapol_key *) (hdr + 1);
3070 pos = (u8 *) (key + 1);
3071 key_data_len = WPA_GET_BE16(pos);
3072 if (key_data_len < AES_BLOCK_SIZE ||
3073 key_data_len > buf_len - sizeof(*hdr) - sizeof(*key) - 2) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07003074 wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003075 "No room for AES-SIV data in the frame");
3076 return -1;
3077 }
3078 pos += 2; /* Pointing at the Encrypted Key Data field */
3079
3080 tmp = os_malloc(key_data_len);
3081 if (!tmp)
3082 return -1;
3083
3084 /* AES-SIV AAD from EAPOL protocol version field (inclusive) to
3085 * to Key Data (exclusive). */
3086 aad[0] = buf;
3087 aad_len[0] = pos - buf;
3088 if (aes_siv_decrypt(ptk->kek, ptk->kek_len, pos, key_data_len,
3089 1, aad, aad_len, tmp) < 0) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07003090 wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003091 "Invalid AES-SIV data in the frame");
3092 bin_clear_free(tmp, key_data_len);
3093 return -1;
3094 }
3095
3096 /* AEAD decryption and validation completed successfully */
3097 key_data_len -= AES_BLOCK_SIZE;
3098 wpa_hexdump_key(MSG_DEBUG, "WPA: Decrypted Key Data",
3099 tmp, key_data_len);
3100
3101 /* Replace Key Data field with the decrypted version */
3102 os_memcpy(pos, tmp, key_data_len);
3103 pos -= 2; /* Key Data Length field */
3104 WPA_PUT_BE16(pos, key_data_len);
3105 bin_clear_free(tmp, key_data_len);
3106 if (_key_data_len)
3107 *_key_data_len = key_data_len;
3108 return 0;
3109}
3110
3111
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003112const u8 * wpa_fils_validate_fils_session(struct wpa_state_machine *sm,
3113 const u8 *ies, size_t ies_len,
3114 const u8 *fils_session)
3115{
3116 const u8 *ie, *end;
3117 const u8 *session = NULL;
3118
3119 if (!wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
3120 wpa_printf(MSG_DEBUG,
3121 "FILS: Not a FILS AKM - reject association");
3122 return NULL;
3123 }
3124
3125 /* Verify Session element */
3126 ie = ies;
3127 end = ((const u8 *) ie) + ies_len;
3128 while (ie + 1 < end) {
3129 if (ie + 2 + ie[1] > end)
3130 break;
3131 if (ie[0] == WLAN_EID_EXTENSION &&
3132 ie[1] >= 1 + FILS_SESSION_LEN &&
3133 ie[2] == WLAN_EID_EXT_FILS_SESSION) {
3134 session = ie;
3135 break;
3136 }
3137 ie += 2 + ie[1];
3138 }
3139
3140 if (!session) {
3141 wpa_printf(MSG_DEBUG,
3142 "FILS: %s: Could not find FILS Session element in Assoc Req - reject",
3143 __func__);
3144 return NULL;
3145 }
3146
3147 if (!fils_session) {
3148 wpa_printf(MSG_DEBUG,
3149 "FILS: %s: Could not find FILS Session element in STA entry - reject",
3150 __func__);
3151 return NULL;
3152 }
3153
3154 if (os_memcmp(fils_session, session + 3, FILS_SESSION_LEN) != 0) {
3155 wpa_printf(MSG_DEBUG, "FILS: Session mismatch");
3156 wpa_hexdump(MSG_DEBUG, "FILS: Expected FILS Session",
3157 fils_session, FILS_SESSION_LEN);
3158 wpa_hexdump(MSG_DEBUG, "FILS: Received FILS Session",
3159 session + 3, FILS_SESSION_LEN);
3160 return NULL;
3161 }
3162 return session;
3163}
3164
3165
3166int wpa_fils_validate_key_confirm(struct wpa_state_machine *sm, const u8 *ies,
3167 size_t ies_len)
3168{
3169 struct ieee802_11_elems elems;
3170
3171 if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed) {
3172 wpa_printf(MSG_DEBUG,
3173 "FILS: Failed to parse decrypted elements");
3174 return -1;
3175 }
3176
3177 if (!elems.fils_session) {
3178 wpa_printf(MSG_DEBUG, "FILS: No FILS Session element");
3179 return -1;
3180 }
3181
3182 if (!elems.fils_key_confirm) {
3183 wpa_printf(MSG_DEBUG, "FILS: No FILS Key Confirm element");
3184 return -1;
3185 }
3186
3187 if (elems.fils_key_confirm_len != sm->fils_key_auth_len) {
3188 wpa_printf(MSG_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07003189 "FILS: Unexpected Key-Auth length %d (expected %zu)",
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003190 elems.fils_key_confirm_len,
Hai Shalomfdcde762020-04-02 11:19:20 -07003191 sm->fils_key_auth_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003192 return -1;
3193 }
3194
3195 if (os_memcmp(elems.fils_key_confirm, sm->fils_key_auth_sta,
3196 sm->fils_key_auth_len) != 0) {
3197 wpa_printf(MSG_DEBUG, "FILS: Key-Auth mismatch");
3198 wpa_hexdump(MSG_DEBUG, "FILS: Received Key-Auth",
3199 elems.fils_key_confirm, elems.fils_key_confirm_len);
3200 wpa_hexdump(MSG_DEBUG, "FILS: Expected Key-Auth",
3201 sm->fils_key_auth_sta, sm->fils_key_auth_len);
3202 return -1;
3203 }
3204
3205 return 0;
3206}
3207
3208
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003209int fils_decrypt_assoc(struct wpa_state_machine *sm, const u8 *fils_session,
3210 const struct ieee80211_mgmt *mgmt, size_t frame_len,
3211 u8 *pos, size_t left)
3212{
3213 u16 fc, stype;
3214 const u8 *end, *ie_start, *ie, *session, *crypt;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003215 const u8 *aad[5];
3216 size_t aad_len[5];
3217
3218 if (!sm || !sm->PTK_valid) {
3219 wpa_printf(MSG_DEBUG,
3220 "FILS: No KEK to decrypt Assocication Request frame");
3221 return -1;
3222 }
3223
3224 if (!wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
3225 wpa_printf(MSG_DEBUG,
3226 "FILS: Not a FILS AKM - reject association");
3227 return -1;
3228 }
3229
3230 end = ((const u8 *) mgmt) + frame_len;
3231 fc = le_to_host16(mgmt->frame_control);
3232 stype = WLAN_FC_GET_STYPE(fc);
3233 if (stype == WLAN_FC_STYPE_REASSOC_REQ)
3234 ie_start = mgmt->u.reassoc_req.variable;
3235 else
3236 ie_start = mgmt->u.assoc_req.variable;
3237 ie = ie_start;
3238
3239 /*
3240 * Find FILS Session element which is the last unencrypted element in
3241 * the frame.
3242 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003243 session = wpa_fils_validate_fils_session(sm, ie, end - ie,
3244 fils_session);
3245 if (!session) {
3246 wpa_printf(MSG_DEBUG, "FILS: Session validation failed");
3247 return -1;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003248 }
3249
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003250 crypt = session + 2 + session[1];
3251
3252 if (end - crypt < AES_BLOCK_SIZE) {
3253 wpa_printf(MSG_DEBUG,
3254 "FILS: Too short frame to include AES-SIV data");
3255 return -1;
3256 }
3257
3258 /* AES-SIV AAD vectors */
3259
3260 /* The STA's MAC address */
3261 aad[0] = mgmt->sa;
3262 aad_len[0] = ETH_ALEN;
3263 /* The AP's BSSID */
3264 aad[1] = mgmt->da;
3265 aad_len[1] = ETH_ALEN;
3266 /* The STA's nonce */
3267 aad[2] = sm->SNonce;
3268 aad_len[2] = FILS_NONCE_LEN;
3269 /* The AP's nonce */
3270 aad[3] = sm->ANonce;
3271 aad_len[3] = FILS_NONCE_LEN;
3272 /*
3273 * The (Re)Association Request frame from the Capability Information
3274 * field to the FILS Session element (both inclusive).
3275 */
3276 aad[4] = (const u8 *) &mgmt->u.assoc_req.capab_info;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003277 aad_len[4] = crypt - aad[4];
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003278
3279 if (aes_siv_decrypt(sm->PTK.kek, sm->PTK.kek_len, crypt, end - crypt,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003280 5, aad, aad_len, pos + (crypt - ie_start)) < 0) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003281 wpa_printf(MSG_DEBUG,
3282 "FILS: Invalid AES-SIV data in the frame");
3283 return -1;
3284 }
3285 wpa_hexdump(MSG_DEBUG, "FILS: Decrypted Association Request elements",
3286 pos, left - AES_BLOCK_SIZE);
3287
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003288 if (wpa_fils_validate_key_confirm(sm, pos, left - AES_BLOCK_SIZE) < 0) {
3289 wpa_printf(MSG_DEBUG, "FILS: Key Confirm validation failed");
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003290 return -1;
3291 }
3292
3293 return left - AES_BLOCK_SIZE;
3294}
3295
3296
3297int fils_encrypt_assoc(struct wpa_state_machine *sm, u8 *buf,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003298 size_t current_len, size_t max_len,
3299 const struct wpabuf *hlp)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003300{
3301 u8 *end = buf + max_len;
3302 u8 *pos = buf + current_len;
3303 struct ieee80211_mgmt *mgmt;
3304 struct wpabuf *plain;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003305 const u8 *aad[5];
3306 size_t aad_len[5];
3307
3308 if (!sm || !sm->PTK_valid)
3309 return -1;
3310
3311 wpa_hexdump(MSG_DEBUG,
3312 "FILS: Association Response frame before FILS processing",
3313 buf, current_len);
3314
3315 mgmt = (struct ieee80211_mgmt *) buf;
3316
3317 /* AES-SIV AAD vectors */
3318
3319 /* The AP's BSSID */
3320 aad[0] = mgmt->sa;
3321 aad_len[0] = ETH_ALEN;
3322 /* The STA's MAC address */
3323 aad[1] = mgmt->da;
3324 aad_len[1] = ETH_ALEN;
3325 /* The AP's nonce */
3326 aad[2] = sm->ANonce;
3327 aad_len[2] = FILS_NONCE_LEN;
3328 /* The STA's nonce */
3329 aad[3] = sm->SNonce;
3330 aad_len[3] = FILS_NONCE_LEN;
3331 /*
3332 * The (Re)Association Response frame from the Capability Information
3333 * field (the same offset in both Association and Reassociation
3334 * Response frames) to the FILS Session element (both inclusive).
3335 */
3336 aad[4] = (const u8 *) &mgmt->u.assoc_resp.capab_info;
3337 aad_len[4] = pos - aad[4];
3338
3339 /* The following elements will be encrypted with AES-SIV */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003340 plain = fils_prepare_plainbuf(sm, hlp);
3341 if (!plain) {
3342 wpa_printf(MSG_DEBUG, "FILS: Plain buffer prep failed");
3343 return -1;
3344 }
3345
3346 if (pos + wpabuf_len(plain) + AES_BLOCK_SIZE > end) {
3347 wpa_printf(MSG_DEBUG,
3348 "FILS: Not enough room for FILS elements");
Hai Shalom81f62d82019-07-22 12:10:00 -07003349 wpabuf_clear_free(plain);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003350 return -1;
3351 }
3352
3353 wpa_hexdump_buf_key(MSG_DEBUG, "FILS: Association Response plaintext",
3354 plain);
3355
3356 if (aes_siv_encrypt(sm->PTK.kek, sm->PTK.kek_len,
3357 wpabuf_head(plain), wpabuf_len(plain),
3358 5, aad, aad_len, pos) < 0) {
Hai Shalom81f62d82019-07-22 12:10:00 -07003359 wpabuf_clear_free(plain);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003360 return -1;
3361 }
3362
3363 wpa_hexdump(MSG_DEBUG,
3364 "FILS: Encrypted Association Response elements",
3365 pos, AES_BLOCK_SIZE + wpabuf_len(plain));
3366 current_len += wpabuf_len(plain) + AES_BLOCK_SIZE;
Hai Shalom81f62d82019-07-22 12:10:00 -07003367 wpabuf_clear_free(plain);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003368
3369 sm->fils_completed = 1;
3370
3371 return current_len;
3372}
3373
3374
3375static struct wpabuf * fils_prepare_plainbuf(struct wpa_state_machine *sm,
3376 const struct wpabuf *hlp)
3377{
3378 struct wpabuf *plain;
3379 u8 *len, *tmp, *tmp2;
3380 u8 hdr[2];
Hai Shaloma20dcd72022-02-04 13:43:00 -08003381 u8 *gtk, stub_gtk[32];
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003382 size_t gtk_len;
3383 struct wpa_group *gsm;
Hai Shalomfdcde762020-04-02 11:19:20 -07003384 size_t plain_len;
3385 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003386
Hai Shalomfdcde762020-04-02 11:19:20 -07003387 plain_len = 1000 + ieee80211w_kde_len(sm);
3388 if (conf->transition_disable)
3389 plain_len += 2 + RSN_SELECTOR_LEN + 1;
3390 plain = wpabuf_alloc(plain_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003391 if (!plain)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003392 return NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003393
3394 /* TODO: FILS Public Key */
3395
3396 /* FILS Key Confirmation */
3397 wpabuf_put_u8(plain, WLAN_EID_EXTENSION); /* Element ID */
3398 wpabuf_put_u8(plain, 1 + sm->fils_key_auth_len); /* Length */
3399 /* Element ID Extension */
3400 wpabuf_put_u8(plain, WLAN_EID_EXT_FILS_KEY_CONFIRM);
3401 wpabuf_put_data(plain, sm->fils_key_auth_ap, sm->fils_key_auth_len);
3402
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003403 /* FILS HLP Container */
3404 if (hlp)
3405 wpabuf_put_buf(plain, hlp);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003406
3407 /* TODO: FILS IP Address Assignment */
3408
3409 /* Key Delivery */
3410 gsm = sm->group;
3411 wpabuf_put_u8(plain, WLAN_EID_EXTENSION); /* Element ID */
3412 len = wpabuf_put(plain, 1);
3413 wpabuf_put_u8(plain, WLAN_EID_EXT_KEY_DELIVERY);
3414 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN,
3415 wpabuf_put(plain, WPA_KEY_RSC_LEN));
3416 /* GTK KDE */
3417 gtk = gsm->GTK[gsm->GN - 1];
3418 gtk_len = gsm->GTK_len;
Hai Shalomfdcde762020-04-02 11:19:20 -07003419 if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003420 /*
3421 * Provide unique random GTK to each STA to prevent use
3422 * of GTK in the BSS.
3423 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003424 if (random_get_bytes(stub_gtk, gtk_len) < 0) {
Hai Shalom81f62d82019-07-22 12:10:00 -07003425 wpabuf_clear_free(plain);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003426 return NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003427 }
Hai Shaloma20dcd72022-02-04 13:43:00 -08003428 gtk = stub_gtk;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003429 }
3430 hdr[0] = gsm->GN & 0x03;
3431 hdr[1] = 0;
3432 tmp = wpabuf_put(plain, 0);
3433 tmp2 = wpa_add_kde(tmp, RSN_KEY_DATA_GROUPKEY, hdr, 2,
3434 gtk, gtk_len);
3435 wpabuf_put(plain, tmp2 - tmp);
3436
Hai Shalomfdcde762020-04-02 11:19:20 -07003437 /* IGTK KDE and BIGTK KDE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003438 tmp = wpabuf_put(plain, 0);
3439 tmp2 = ieee80211w_kde_add(sm, tmp);
3440 wpabuf_put(plain, tmp2 - tmp);
3441
Hai Shalomfdcde762020-04-02 11:19:20 -07003442 if (conf->transition_disable) {
3443 tmp = wpabuf_put(plain, 0);
3444 tmp2 = wpa_add_kde(tmp, WFA_KEY_DATA_TRANSITION_DISABLE,
3445 &conf->transition_disable, 1, NULL, 0);
3446 wpabuf_put(plain, tmp2 - tmp);
3447 }
3448
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003449 *len = (u8 *) wpabuf_put(plain, 0) - len - 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08003450
3451#ifdef CONFIG_OCV
3452 if (wpa_auth_uses_ocv(sm)) {
3453 struct wpa_channel_info ci;
3454 u8 *pos;
3455
3456 if (wpa_channel_info(sm->wpa_auth, &ci) != 0) {
3457 wpa_printf(MSG_WARNING,
3458 "FILS: Failed to get channel info for OCI element");
Hai Shalom81f62d82019-07-22 12:10:00 -07003459 wpabuf_clear_free(plain);
Hai Shalom74f70d42019-02-11 14:42:39 -08003460 return NULL;
3461 }
Hai Shalom899fcc72020-10-19 14:38:18 -07003462#ifdef CONFIG_TESTING_OPTIONS
3463 if (conf->oci_freq_override_fils_assoc) {
3464 wpa_printf(MSG_INFO,
3465 "TEST: Override OCI frequency %d -> %u MHz",
3466 ci.frequency,
3467 conf->oci_freq_override_fils_assoc);
3468 ci.frequency = conf->oci_freq_override_fils_assoc;
3469 }
3470#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom74f70d42019-02-11 14:42:39 -08003471
3472 pos = wpabuf_put(plain, OCV_OCI_EXTENDED_LEN);
3473 if (ocv_insert_extended_oci(&ci, pos) < 0) {
Hai Shalom81f62d82019-07-22 12:10:00 -07003474 wpabuf_clear_free(plain);
Hai Shalom74f70d42019-02-11 14:42:39 -08003475 return NULL;
3476 }
3477 }
3478#endif /* CONFIG_OCV */
3479
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003480 return plain;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003481}
3482
3483
3484int fils_set_tk(struct wpa_state_machine *sm)
3485{
3486 enum wpa_alg alg;
3487 int klen;
3488
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003489 if (!sm || !sm->PTK_valid) {
3490 wpa_printf(MSG_DEBUG, "FILS: No valid PTK available to set TK");
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003491 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003492 }
3493 if (sm->tk_already_set) {
3494 wpa_printf(MSG_DEBUG, "FILS: TK already set to the driver");
3495 return -1;
3496 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003497
3498 alg = wpa_cipher_to_alg(sm->pairwise);
3499 klen = wpa_cipher_key_len(sm->pairwise);
3500
3501 wpa_printf(MSG_DEBUG, "FILS: Configure TK to the driver");
3502 if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0,
Hai Shalomfdcde762020-04-02 11:19:20 -07003503 sm->PTK.tk, klen, KEY_FLAG_PAIRWISE_RX_TX)) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003504 wpa_printf(MSG_DEBUG, "FILS: Failed to set TK to the driver");
3505 return -1;
3506 }
Sunil Ravi89eba102022-09-13 21:04:37 -07003507
3508#ifdef CONFIG_PASN
3509 if (sm->wpa_auth->conf.secure_ltf &&
3510 ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF) &&
3511 wpa_auth_set_ltf_keyseed(sm->wpa_auth, sm->addr,
3512 sm->PTK.ltf_keyseed,
3513 sm->PTK.ltf_keyseed_len)) {
3514 wpa_printf(MSG_ERROR,
3515 "FILS: Failed to set LTF keyseed to driver");
3516 return -1;
3517 }
3518#endif /* CONFIG_PASN */
3519
Sunil8cd6f4d2022-06-28 18:40:46 +00003520 sm->pairwise_set = true;
Hai Shalome21d4e82020-04-29 16:34:06 -07003521 sm->tk_already_set = true;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003522
Hai Shalom60840252021-02-19 19:02:11 -08003523 wpa_auth_store_ptksa(sm->wpa_auth, sm->addr, sm->pairwise,
3524 dot11RSNAConfigPMKLifetime, &sm->PTK);
3525
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003526 return 0;
3527}
3528
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003529
3530u8 * hostapd_eid_assoc_fils_session(struct wpa_state_machine *sm, u8 *buf,
3531 const u8 *fils_session, struct wpabuf *hlp)
3532{
3533 struct wpabuf *plain;
3534 u8 *pos = buf;
3535
3536 /* FILS Session */
3537 *pos++ = WLAN_EID_EXTENSION; /* Element ID */
3538 *pos++ = 1 + FILS_SESSION_LEN; /* Length */
3539 *pos++ = WLAN_EID_EXT_FILS_SESSION; /* Element ID Extension */
3540 os_memcpy(pos, fils_session, FILS_SESSION_LEN);
3541 pos += FILS_SESSION_LEN;
3542
3543 plain = fils_prepare_plainbuf(sm, hlp);
3544 if (!plain) {
3545 wpa_printf(MSG_DEBUG, "FILS: Plain buffer prep failed");
3546 return NULL;
3547 }
3548
3549 os_memcpy(pos, wpabuf_head(plain), wpabuf_len(plain));
3550 pos += wpabuf_len(plain);
3551
Hai Shalomfdcde762020-04-02 11:19:20 -07003552 wpa_printf(MSG_DEBUG, "%s: plain buf_len: %zu", __func__,
3553 wpabuf_len(plain));
Hai Shalom81f62d82019-07-22 12:10:00 -07003554 wpabuf_clear_free(plain);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003555 sm->fils_completed = 1;
3556 return pos;
3557}
3558
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003559#endif /* CONFIG_FILS */
3560
3561
Hai Shalom74f70d42019-02-11 14:42:39 -08003562#ifdef CONFIG_OCV
3563int get_sta_tx_parameters(struct wpa_state_machine *sm, int ap_max_chanwidth,
3564 int ap_seg1_idx, int *bandwidth, int *seg1_idx)
3565{
3566 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
3567
3568 if (!wpa_auth->cb->get_sta_tx_params)
3569 return -1;
3570 return wpa_auth->cb->get_sta_tx_params(wpa_auth->cb_ctx, sm->addr,
3571 ap_max_chanwidth, ap_seg1_idx,
3572 bandwidth, seg1_idx);
3573}
3574#endif /* CONFIG_OCV */
3575
3576
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003577static int wpa_auth_validate_ml_kdes_m2(struct wpa_state_machine *sm,
3578 struct wpa_eapol_ie_parse *kde)
3579{
3580#ifdef CONFIG_IEEE80211BE
3581 int i;
3582 unsigned int n_links = 0;
3583
3584 if (sm->mld_assoc_link_id < 0)
3585 return 0;
3586
3587 /* MLD MAC address must be the same */
3588 if (!kde->mac_addr ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003589 !ether_addr_equal(kde->mac_addr, sm->peer_mld_addr)) {
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003590 wpa_printf(MSG_DEBUG, "RSN: MLD: Invalid MLD address");
3591 return -1;
3592 }
3593
3594 /* Find matching link ID and the MAC address for each link */
Sunil Ravi99c035e2024-07-12 01:42:03 +00003595 for_each_link(kde->valid_mlo_links, i) {
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003596 /*
3597 * Each entry should contain the link information and the MAC
3598 * address.
3599 */
3600 if (kde->mlo_link_len[i] != 1 + ETH_ALEN) {
3601 wpa_printf(MSG_DEBUG,
3602 "RSN: MLD: Invalid MLO Link (ID %u) KDE len=%zu",
3603 i, kde->mlo_link_len[i]);
3604 return -1;
3605 }
3606
3607 if (!sm->mld_links[i].valid || i == sm->mld_assoc_link_id) {
3608 wpa_printf(MSG_DEBUG,
3609 "RSN: MLD: Invalid link ID=%u", i);
3610 return -1;
3611 }
3612
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003613 if (!ether_addr_equal(sm->mld_links[i].peer_addr,
3614 kde->mlo_link[i] + 1)) {
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003615 wpa_printf(MSG_DEBUG,
3616 "RSN: MLD: invalid MAC address=" MACSTR
3617 " expected " MACSTR " (link ID %u)",
3618 MAC2STR(kde->mlo_link[i] + 1),
3619 MAC2STR(sm->mld_links[i].peer_addr), i);
3620 return -1;
3621 }
3622
3623 n_links++;
3624 }
3625
3626 /* Must have the same number of MLO links (excluding the local one) */
3627 if (n_links != sm->n_mld_affiliated_links) {
3628 wpa_printf(MSG_DEBUG,
3629 "RSN: MLD: Expecting %u MLD links in msg 2, but got %u",
3630 sm->n_mld_affiliated_links, n_links);
3631 return -1;
3632 }
3633#endif /* CONFIG_IEEE80211BE */
3634
3635 return 0;
3636}
3637
3638
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003639SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
3640{
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003641 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003642 struct wpa_ptk PTK;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07003643 int ok = 0, psk_found = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003644 const u8 *pmk = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003645 size_t pmk_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003646 int ft;
3647 const u8 *eapol_key_ie, *key_data, *mic;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003648 u16 key_info, ver, key_data_length;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003649 size_t mic_len, eapol_key_ie_len;
3650 struct ieee802_1x_hdr *hdr;
3651 struct wpa_eapol_key *key;
3652 struct wpa_eapol_ie_parse kde;
Hai Shalom021b0b52019-04-10 11:17:58 -07003653 int vlan_id = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003654 int owe_ptk_workaround = !!wpa_auth->conf.owe_ptk_workaround;
Sunil Raviaf8751c2023-03-29 11:35:17 -07003655 u8 pmk_r0[PMK_LEN_MAX], pmk_r0_name[WPA_PMK_NAME_LEN];
3656 u8 pmk_r1[PMK_LEN_MAX];
3657 size_t key_len;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003658 u8 *key_data_buf = NULL;
3659 size_t key_data_buf_len = 0;
Sunil Ravi7f769292024-07-23 22:21:32 +00003660 bool derive_kdk, no_kdk = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003661
3662 SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07003663 sm->EAPOLKeyReceived = false;
3664 sm->update_snonce = false;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003665 os_memset(&PTK, 0, sizeof(PTK));
3666
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003667 mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003668
Sunil Ravi7f769292024-07-23 22:21:32 +00003669 derive_kdk = sm->wpa_auth->conf.secure_ltf &&
3670 ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF);
3671
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003672 /* WPA with IEEE 802.1X: use the derived PMK from EAP
3673 * WPA-PSK: iterate through possible PSKs and select the one matching
3674 * the packet */
3675 for (;;) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003676 if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
3677 !wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07003678 pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr,
Hai Shalom021b0b52019-04-10 11:17:58 -07003679 sm->p2p_dev_addr, pmk, &pmk_len,
3680 &vlan_id);
Hai Shalomfdcde762020-04-02 11:19:20 -07003681 if (!pmk)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003682 break;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07003683 psk_found = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003684#ifdef CONFIG_IEEE80211R_AP
3685 if (wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) {
3686 os_memcpy(sm->xxkey, pmk, pmk_len);
3687 sm->xxkey_len = pmk_len;
3688 }
3689#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003690 } else {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003691 pmk = sm->PMK;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003692 pmk_len = sm->pmk_len;
3693 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003694
Hai Shalom81f62d82019-07-22 12:10:00 -07003695 if ((!pmk || !pmk_len) && sm->pmksa) {
3696 wpa_printf(MSG_DEBUG, "WPA: Use PMK from PMKSA cache");
3697 pmk = sm->pmksa->pmk;
3698 pmk_len = sm->pmksa->pmk_len;
3699 }
3700
Sunil Ravi7f769292024-07-23 22:21:32 +00003701 no_kdk = false;
3702 try_without_kdk:
Hai Shalomfdcde762020-04-02 11:19:20 -07003703 if (wpa_derive_ptk(sm, sm->SNonce, pmk, pmk_len, &PTK,
Sunil Raviaf8751c2023-03-29 11:35:17 -07003704 owe_ptk_workaround == 2, pmk_r0, pmk_r1,
Sunil Ravi7f769292024-07-23 22:21:32 +00003705 pmk_r0_name, &key_len, no_kdk) < 0)
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003706 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003707
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003708 if (mic_len &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003709 wpa_verify_key_mic(sm->wpa_key_mgmt, pmk_len, &PTK,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003710 sm->last_rx_eapol_key,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003711 sm->last_rx_eapol_key_len) == 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07003712 if (sm->PMK != pmk) {
3713 os_memcpy(sm->PMK, pmk, pmk_len);
3714 sm->pmk_len = pmk_len;
3715 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003716 ok = 1;
3717 break;
3718 }
3719
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003720#ifdef CONFIG_FILS
3721 if (!mic_len &&
3722 wpa_aead_decrypt(sm, &PTK, sm->last_rx_eapol_key,
3723 sm->last_rx_eapol_key_len, NULL) == 0) {
3724 ok = 1;
3725 break;
3726 }
3727#endif /* CONFIG_FILS */
3728
Hai Shalomfdcde762020-04-02 11:19:20 -07003729#ifdef CONFIG_OWE
3730 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE && pmk_len > 32 &&
3731 owe_ptk_workaround == 1) {
3732 wpa_printf(MSG_DEBUG,
3733 "OWE: Try PTK derivation workaround with SHA256");
3734 owe_ptk_workaround = 2;
3735 continue;
3736 }
3737#endif /* CONFIG_OWE */
3738
Sunil Ravi7f769292024-07-23 22:21:32 +00003739 /* Some deployed STAs that advertise SecureLTF support in the
3740 * RSNXE in (Re)Association Request frames, do not derive KDK
3741 * during PTK generation. Try to work around this by checking if
3742 * a PTK derived without KDK would result in a matching MIC. */
3743 if (!sm->wpa_auth->conf.force_kdk_derivation &&
3744 derive_kdk && !no_kdk) {
3745 wpa_printf(MSG_DEBUG,
3746 "Try new PTK derivation without KDK as a workaround");
3747 no_kdk = true;
3748 goto try_without_kdk;
3749 }
3750
Roshan Pius3a1667e2018-07-03 15:17:14 -07003751 if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
3752 wpa_key_mgmt_sae(sm->wpa_key_mgmt))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003753 break;
3754 }
3755
Sunil Ravi7f769292024-07-23 22:21:32 +00003756 if (no_kdk && ok) {
3757 /* The workaround worked, so allow the 4-way handshake to be
3758 * completed with the PTK that was derived without the KDK. */
3759 wpa_printf(MSG_DEBUG,
3760 "PTK without KDK worked - misbehaving STA "
3761 MACSTR, MAC2STR(sm->addr));
3762 }
3763
Sunil Ravia04bd252022-05-02 22:54:18 -07003764 if (!ok && wpa_key_mgmt_wpa_psk_no_sae(sm->wpa_key_mgmt) &&
3765 wpa_auth->conf.radius_psk && wpa_auth->cb->request_radius_psk &&
3766 !sm->waiting_radius_psk) {
3767 wpa_printf(MSG_DEBUG, "No PSK available - ask RADIUS server");
3768 wpa_auth->cb->request_radius_psk(wpa_auth->cb_ctx, sm->addr,
3769 sm->wpa_key_mgmt,
3770 sm->ANonce,
3771 sm->last_rx_eapol_key,
3772 sm->last_rx_eapol_key_len);
3773 sm->waiting_radius_psk = 1;
Sunil Raviaf8751c2023-03-29 11:35:17 -07003774 goto out;
Sunil Ravia04bd252022-05-02 22:54:18 -07003775 }
3776
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003777 if (!ok) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07003778 wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm),
3779 LOGGER_DEBUG,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003780 "invalid MIC in msg 2/4 of 4-Way Handshake");
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07003781 if (psk_found)
3782 wpa_auth_psk_failure_report(sm->wpa_auth, sm->addr);
Sunil Raviaf8751c2023-03-29 11:35:17 -07003783 goto out;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003784 }
3785
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003786 /*
3787 * Note: last_rx_eapol_key length fields have already been validated in
3788 * wpa_receive().
3789 */
3790 hdr = (struct ieee802_1x_hdr *) sm->last_rx_eapol_key;
3791 key = (struct wpa_eapol_key *) (hdr + 1);
3792 mic = (u8 *) (key + 1);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003793 key_info = WPA_GET_BE16(key->key_info);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003794 key_data = mic + mic_len + 2;
3795 key_data_length = WPA_GET_BE16(mic + mic_len);
3796 if (key_data_length > sm->last_rx_eapol_key_len - sizeof(*hdr) -
3797 sizeof(*key) - mic_len - 2)
Sunil Raviaf8751c2023-03-29 11:35:17 -07003798 goto out;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003799
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003800 ver = key_info & WPA_KEY_INFO_TYPE_MASK;
3801 if (mic_len && (key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
3802 if (ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES &&
3803 ver != WPA_KEY_INFO_TYPE_AES_128_CMAC &&
3804 !wpa_use_aes_key_wrap(sm->wpa_key_mgmt)) {
3805 wpa_printf(MSG_INFO,
3806 "Unsupported EAPOL-Key Key Data field encryption");
3807 goto out;
3808 }
3809
3810 if (key_data_length < 8 || key_data_length % 8) {
3811 wpa_printf(MSG_INFO,
3812 "RSN: Unsupported AES-WRAP len %u",
3813 key_data_length);
3814 goto out;
3815 }
3816 key_data_length -= 8; /* AES-WRAP adds 8 bytes */
3817 key_data_buf = os_malloc(key_data_length);
3818 if (!key_data_buf)
3819 goto out;
3820 key_data_buf_len = key_data_length;
3821 if (aes_unwrap(PTK.kek, PTK.kek_len, key_data_length / 8,
3822 key_data, key_data_buf)) {
3823 bin_clear_free(key_data_buf, key_data_buf_len);
3824 wpa_printf(MSG_INFO,
3825 "RSN: AES unwrap failed - could not decrypt EAPOL-Key key data");
3826 goto out;
3827 }
3828 key_data = key_data_buf;
3829 wpa_hexdump_key(MSG_DEBUG, "RSN: Decrypted EAPOL-Key Key Data",
3830 key_data, key_data_length);
3831 }
3832
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003833 if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07003834 wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003835 "received EAPOL-Key msg 2/4 with invalid Key Data contents");
Sunil Raviaf8751c2023-03-29 11:35:17 -07003836 goto out;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003837 }
3838 if (kde.rsn_ie) {
3839 eapol_key_ie = kde.rsn_ie;
3840 eapol_key_ie_len = kde.rsn_ie_len;
3841 } else if (kde.osen) {
3842 eapol_key_ie = kde.osen;
3843 eapol_key_ie_len = kde.osen_len;
3844 } else {
3845 eapol_key_ie = kde.wpa_ie;
3846 eapol_key_ie_len = kde.wpa_ie_len;
3847 }
3848 ft = sm->wpa == WPA_VERSION_WPA2 && wpa_key_mgmt_ft(sm->wpa_key_mgmt);
Hai Shalomfdcde762020-04-02 11:19:20 -07003849 if (!sm->wpa_ie ||
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003850 wpa_compare_rsn_ie(ft, sm->wpa_ie, sm->wpa_ie_len,
3851 eapol_key_ie, eapol_key_ie_len)) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07003852 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003853 "WPA IE from (Re)AssocReq did not match with msg 2/4");
3854 if (sm->wpa_ie) {
3855 wpa_hexdump(MSG_DEBUG, "WPA IE in AssocReq",
3856 sm->wpa_ie, sm->wpa_ie_len);
3857 }
3858 wpa_hexdump(MSG_DEBUG, "WPA IE in msg 2/4",
3859 eapol_key_ie, eapol_key_ie_len);
3860 /* MLME-DEAUTHENTICATE.request */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003861 wpa_sta_disconnect(wpa_auth, sm->addr,
3862 WLAN_REASON_PREV_AUTH_NOT_VALID);
Sunil Raviaf8751c2023-03-29 11:35:17 -07003863 goto out;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003864 }
Hai Shalomc3565922019-10-28 11:58:20 -07003865 if ((!sm->rsnxe && kde.rsnxe) ||
3866 (sm->rsnxe && !kde.rsnxe) ||
3867 (sm->rsnxe && kde.rsnxe &&
3868 (sm->rsnxe_len != kde.rsnxe_len ||
3869 os_memcmp(sm->rsnxe, kde.rsnxe, sm->rsnxe_len) != 0))) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07003870 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
Hai Shalomc3565922019-10-28 11:58:20 -07003871 "RSNXE from (Re)AssocReq did not match the one in EAPOL-Key msg 2/4");
3872 wpa_hexdump(MSG_DEBUG, "RSNXE in AssocReq",
3873 sm->rsnxe, sm->rsnxe_len);
3874 wpa_hexdump(MSG_DEBUG, "RSNXE in EAPOL-Key msg 2/4",
3875 kde.rsnxe, kde.rsnxe_len);
3876 /* MLME-DEAUTHENTICATE.request */
3877 wpa_sta_disconnect(wpa_auth, sm->addr,
3878 WLAN_REASON_PREV_AUTH_NOT_VALID);
Sunil Raviaf8751c2023-03-29 11:35:17 -07003879 goto out;
Hai Shalomc3565922019-10-28 11:58:20 -07003880 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003881#ifdef CONFIG_OCV
3882 if (wpa_auth_uses_ocv(sm)) {
3883 struct wpa_channel_info ci;
3884 int tx_chanwidth;
3885 int tx_seg1_idx;
Hai Shalom899fcc72020-10-19 14:38:18 -07003886 enum oci_verify_result res;
Hai Shalom74f70d42019-02-11 14:42:39 -08003887
3888 if (wpa_channel_info(wpa_auth, &ci) != 0) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07003889 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
3890 LOGGER_INFO,
Hai Shalom74f70d42019-02-11 14:42:39 -08003891 "Failed to get channel info to validate received OCI in EAPOL-Key 2/4");
Sunil Raviaf8751c2023-03-29 11:35:17 -07003892 goto out;
Hai Shalom74f70d42019-02-11 14:42:39 -08003893 }
3894
3895 if (get_sta_tx_parameters(sm,
3896 channel_width_to_int(ci.chanwidth),
3897 ci.seg1_idx, &tx_chanwidth,
3898 &tx_seg1_idx) < 0)
Sunil Raviaf8751c2023-03-29 11:35:17 -07003899 goto out;
Hai Shalom74f70d42019-02-11 14:42:39 -08003900
Hai Shalom899fcc72020-10-19 14:38:18 -07003901 res = ocv_verify_tx_params(kde.oci, kde.oci_len, &ci,
3902 tx_chanwidth, tx_seg1_idx);
3903 if (wpa_auth_uses_ocv(sm) == 2 && res == OCI_NOT_FOUND) {
3904 /* Work around misbehaving STAs */
Sunil Raviaf8751c2023-03-29 11:35:17 -07003905 wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
3906 LOGGER_INFO,
Hai Shalom899fcc72020-10-19 14:38:18 -07003907 "Disable OCV with a STA that does not send OCI");
3908 wpa_auth_set_ocv(sm, 0);
3909 } else if (res != OCI_SUCCESS) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07003910 wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
3911 LOGGER_INFO,
Hai Shalom899fcc72020-10-19 14:38:18 -07003912 "OCV failed: %s", ocv_errorstr);
3913 if (wpa_auth->conf.msg_ctx)
3914 wpa_msg(wpa_auth->conf.msg_ctx, MSG_INFO,
3915 OCV_FAILURE "addr=" MACSTR
3916 " frame=eapol-key-m2 error=%s",
Sunil Raviaf8751c2023-03-29 11:35:17 -07003917 MAC2STR(wpa_auth_get_spa(sm)),
3918 ocv_errorstr);
3919 goto out;
Hai Shalom74f70d42019-02-11 14:42:39 -08003920 }
3921 }
3922#endif /* CONFIG_OCV */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003923#ifdef CONFIG_IEEE80211R_AP
3924 if (ft && ft_check_msg_2_of_4(wpa_auth, sm, &kde) < 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003925 wpa_sta_disconnect(wpa_auth, sm->addr,
3926 WLAN_REASON_PREV_AUTH_NOT_VALID);
Sunil Raviaf8751c2023-03-29 11:35:17 -07003927 goto out;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003928 }
3929#endif /* CONFIG_IEEE80211R_AP */
Sunil Ravic0f5d412024-09-11 22:12:49 +00003930
3931 /* Verify RSN Selection element for RSN overriding */
3932 if ((wpa_auth->conf.rsn_override_key_mgmt ||
3933 wpa_auth->conf.rsn_override_key_mgmt_2) &&
3934 ((rsn_is_snonce_cookie(sm->SNonce) && !kde.rsn_selection) ||
3935 (!rsn_is_snonce_cookie(sm->SNonce) && kde.rsn_selection) ||
3936 (sm->rsn_selection && !kde.rsn_selection) ||
3937 (!sm->rsn_selection && kde.rsn_selection) ||
3938 (sm->rsn_selection && kde.rsn_selection &&
3939 (sm->rsn_selection_len != kde.rsn_selection_len ||
3940 os_memcmp(sm->rsn_selection, kde.rsn_selection,
3941 sm->rsn_selection_len) != 0)))) {
3942 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
3943 "RSN Selection element from (Re)AssocReq did not match the one in EAPOL-Key msg 2/4");
3944 wpa_printf(MSG_DEBUG,
3945 "SNonce cookie for RSN overriding %sused",
3946 rsn_is_snonce_cookie(sm->SNonce) ? "" : "not ");
3947 wpa_hexdump(MSG_DEBUG, "RSN Selection in AssocReq",
3948 sm->rsn_selection, sm->rsn_selection_len);
3949 wpa_hexdump(MSG_DEBUG, "RSN Selection in EAPOL-Key msg 2/4",
3950 kde.rsn_selection, kde.rsn_selection_len);
3951 /* MLME-DEAUTHENTICATE.request */
3952 wpa_sta_disconnect(wpa_auth, sm->addr,
3953 WLAN_REASON_PREV_AUTH_NOT_VALID);
3954 goto out;
3955
3956 }
3957
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003958#ifdef CONFIG_P2P
3959 if (kde.ip_addr_req && kde.ip_addr_req[0] &&
3960 wpa_auth->ip_pool && WPA_GET_BE32(sm->ip_addr) == 0) {
3961 int idx;
3962 wpa_printf(MSG_DEBUG,
3963 "P2P: IP address requested in EAPOL-Key exchange");
3964 idx = bitfield_get_first_zero(wpa_auth->ip_pool);
3965 if (idx >= 0) {
3966 u32 start = WPA_GET_BE32(wpa_auth->conf.ip_addr_start);
3967 bitfield_set(wpa_auth->ip_pool, idx);
Sunil8cd6f4d2022-06-28 18:40:46 +00003968 sm->ip_addr_bit = idx;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003969 WPA_PUT_BE32(sm->ip_addr, start + idx);
3970 wpa_printf(MSG_DEBUG,
3971 "P2P: Assigned IP address %u.%u.%u.%u to "
Sunil8cd6f4d2022-06-28 18:40:46 +00003972 MACSTR " (bit %u)",
3973 sm->ip_addr[0], sm->ip_addr[1],
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003974 sm->ip_addr[2], sm->ip_addr[3],
Sunil Raviaf8751c2023-03-29 11:35:17 -07003975 MAC2STR(wpa_auth_get_spa(sm)),
3976 sm->ip_addr_bit);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003977 }
3978 }
3979#endif /* CONFIG_P2P */
3980
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003981#ifdef CONFIG_DPP2
3982 if (DPP_VERSION > 1 && kde.dpp_kde) {
3983 wpa_printf(MSG_DEBUG,
3984 "DPP: peer Protocol Version %u Flags 0x%x",
3985 kde.dpp_kde[0], kde.dpp_kde[1]);
3986 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP &&
3987 wpa_auth->conf.dpp_pfs != 2 &&
3988 (kde.dpp_kde[1] & DPP_KDE_PFS_ALLOWED) &&
3989 !sm->dpp_z) {
3990 wpa_printf(MSG_INFO,
3991 "DPP: Peer indicated it supports PFS and local configuration allows this, but PFS was not negotiated for the association");
3992 wpa_sta_disconnect(wpa_auth, sm->addr,
3993 WLAN_REASON_PREV_AUTH_NOT_VALID);
Sunil Raviaf8751c2023-03-29 11:35:17 -07003994 goto out;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003995 }
3996 }
3997#endif /* CONFIG_DPP2 */
3998
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003999 if (wpa_auth_validate_ml_kdes_m2(sm, &kde) < 0) {
4000 wpa_sta_disconnect(wpa_auth, sm->addr,
4001 WLAN_REASON_PREV_AUTH_NOT_VALID);
4002 return;
4003 }
4004
Hai Shalom021b0b52019-04-10 11:17:58 -07004005 if (vlan_id && wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
4006 wpa_auth_update_vlan(wpa_auth, sm->addr, vlan_id) < 0) {
4007 wpa_sta_disconnect(wpa_auth, sm->addr,
4008 WLAN_REASON_PREV_AUTH_NOT_VALID);
Sunil Raviaf8751c2023-03-29 11:35:17 -07004009 goto out;
Hai Shalom021b0b52019-04-10 11:17:58 -07004010 }
4011
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004012 sm->pending_1_of_4_timeout = 0;
4013 eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm);
4014
Hai Shalom60840252021-02-19 19:02:11 -08004015 if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) && sm->PMK != pmk) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004016 /* PSK may have changed from the previous choice, so update
4017 * state machine data based on whatever PSK was selected here.
4018 */
4019 os_memcpy(sm->PMK, pmk, PMK_LEN);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004020 sm->pmk_len = PMK_LEN;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004021 }
4022
Hai Shalome21d4e82020-04-29 16:34:06 -07004023 sm->MICVerified = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004024
Sunil Raviaf8751c2023-03-29 11:35:17 -07004025#ifdef CONFIG_IEEE80211R_AP
4026 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt) && !sm->ft_completed) {
4027 wpa_printf(MSG_DEBUG, "FT: Store PMK-R0/PMK-R1");
4028 wpa_auth_ft_store_keys(sm, pmk_r0, pmk_r1, pmk_r0_name,
4029 key_len);
4030 }
4031#endif /* CONFIG_IEEE80211R_AP */
4032
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004033 os_memcpy(&sm->PTK, &PTK, sizeof(PTK));
Hai Shalom81f62d82019-07-22 12:10:00 -07004034 forced_memzero(&PTK, sizeof(PTK));
Hai Shalome21d4e82020-04-29 16:34:06 -07004035 sm->PTK_valid = true;
Sunil Raviaf8751c2023-03-29 11:35:17 -07004036out:
4037 forced_memzero(pmk_r0, sizeof(pmk_r0));
4038 forced_memzero(pmk_r1, sizeof(pmk_r1));
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004039 bin_clear_free(key_data_buf, key_data_buf_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004040}
4041
4042
4043SM_STATE(WPA_PTK, PTKCALCNEGOTIATING2)
4044{
4045 SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING2, wpa_ptk);
4046 sm->TimeoutCtr = 0;
4047}
4048
4049
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004050static int ieee80211w_kde_len(struct wpa_state_machine *sm)
4051{
Hai Shalomfdcde762020-04-02 11:19:20 -07004052 size_t len = 0;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004053 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
Hai Shalomfdcde762020-04-02 11:19:20 -07004054
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004055 if (sm->mgmt_frame_prot) {
Hai Shalomfdcde762020-04-02 11:19:20 -07004056 len += 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004057 len += wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher);
Hai Shalomfdcde762020-04-02 11:19:20 -07004058 }
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004059
4060 if (wpa_auth->conf.tx_bss_auth)
4061 wpa_auth = wpa_auth->conf.tx_bss_auth;
Hai Shalomfdcde762020-04-02 11:19:20 -07004062 if (sm->mgmt_frame_prot && sm->wpa_auth->conf.beacon_prot) {
4063 len += 2 + RSN_SELECTOR_LEN + WPA_BIGTK_KDE_PREFIX_LEN;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004064 len += wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004065 }
4066
Hai Shalomfdcde762020-04-02 11:19:20 -07004067 return len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004068}
4069
4070
4071static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos)
4072{
4073 struct wpa_igtk_kde igtk;
Hai Shalomfdcde762020-04-02 11:19:20 -07004074 struct wpa_bigtk_kde bigtk;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004075 struct wpa_group *gsm = sm->group;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004076 u8 rsc[WPA_KEY_RSC_LEN];
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004077 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
4078 struct wpa_auth_config *conf = &wpa_auth->conf;
Hai Shalomfdcde762020-04-02 11:19:20 -07004079 size_t len = wpa_cipher_key_len(conf->group_mgmt_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004080
4081 if (!sm->mgmt_frame_prot)
4082 return pos;
4083
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004084#ifdef CONFIG_IEEE80211BE
4085 if (sm->mld_assoc_link_id >= 0)
4086 return pos; /* Use per-link MLO KDEs instead */
4087#endif /* CONFIG_IEEE80211BE */
4088
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004089 igtk.keyid[0] = gsm->GN_igtk;
4090 igtk.keyid[1] = 0;
4091 if (gsm->wpa_group_state != WPA_GROUP_SETKEYSDONE ||
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004092 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, rsc) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004093 os_memset(igtk.pn, 0, sizeof(igtk.pn));
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004094 else
4095 os_memcpy(igtk.pn, rsc, sizeof(igtk.pn));
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004096 os_memcpy(igtk.igtk, gsm->IGTK[gsm->GN_igtk - 4], len);
Hai Shalomfdcde762020-04-02 11:19:20 -07004097 if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004098 /*
4099 * Provide unique random IGTK to each STA to prevent use of
4100 * IGTK in the BSS.
4101 */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004102 if (random_get_bytes(igtk.igtk, len) < 0)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004103 return pos;
4104 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004105 pos = wpa_add_kde(pos, RSN_KEY_DATA_IGTK,
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004106 (const u8 *) &igtk, WPA_IGTK_KDE_PREFIX_LEN + len,
4107 NULL, 0);
Sunil Ravia04bd252022-05-02 22:54:18 -07004108 forced_memzero(&igtk, sizeof(igtk));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004109
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004110 if (wpa_auth->conf.tx_bss_auth) {
4111 wpa_auth = wpa_auth->conf.tx_bss_auth;
4112 conf = &wpa_auth->conf;
4113 len = wpa_cipher_key_len(conf->group_mgmt_cipher);
4114 gsm = wpa_auth->group;
4115 }
4116
4117 if (!sm->wpa_auth->conf.beacon_prot)
Hai Shalomfdcde762020-04-02 11:19:20 -07004118 return pos;
4119
4120 bigtk.keyid[0] = gsm->GN_bigtk;
4121 bigtk.keyid[1] = 0;
4122 if (gsm->wpa_group_state != WPA_GROUP_SETKEYSDONE ||
4123 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_bigtk, rsc) < 0)
4124 os_memset(bigtk.pn, 0, sizeof(bigtk.pn));
4125 else
4126 os_memcpy(bigtk.pn, rsc, sizeof(bigtk.pn));
4127 os_memcpy(bigtk.bigtk, gsm->BIGTK[gsm->GN_bigtk - 6], len);
Hai Shalom899fcc72020-10-19 14:38:18 -07004128 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
4129 /*
4130 * Provide unique random BIGTK to each OSEN STA to prevent use
4131 * of BIGTK in the BSS.
4132 */
4133 if (random_get_bytes(bigtk.bigtk, len) < 0)
4134 return pos;
4135 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004136 pos = wpa_add_kde(pos, RSN_KEY_DATA_BIGTK,
4137 (const u8 *) &bigtk, WPA_BIGTK_KDE_PREFIX_LEN + len,
4138 NULL, 0);
Sunil Ravia04bd252022-05-02 22:54:18 -07004139 forced_memzero(&bigtk, sizeof(bigtk));
Hai Shalomfdcde762020-04-02 11:19:20 -07004140
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004141 return pos;
4142}
4143
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004144
Hai Shalom74f70d42019-02-11 14:42:39 -08004145static int ocv_oci_len(struct wpa_state_machine *sm)
4146{
4147#ifdef CONFIG_OCV
4148 if (wpa_auth_uses_ocv(sm))
4149 return OCV_OCI_KDE_LEN;
4150#endif /* CONFIG_OCV */
4151 return 0;
4152}
4153
Hai Shalom899fcc72020-10-19 14:38:18 -07004154
4155static int ocv_oci_add(struct wpa_state_machine *sm, u8 **argpos,
4156 unsigned int freq)
Hai Shalom74f70d42019-02-11 14:42:39 -08004157{
4158#ifdef CONFIG_OCV
4159 struct wpa_channel_info ci;
4160
4161 if (!wpa_auth_uses_ocv(sm))
4162 return 0;
4163
4164 if (wpa_channel_info(sm->wpa_auth, &ci) != 0) {
4165 wpa_printf(MSG_WARNING,
4166 "Failed to get channel info for OCI element");
4167 return -1;
4168 }
Hai Shalom899fcc72020-10-19 14:38:18 -07004169#ifdef CONFIG_TESTING_OPTIONS
4170 if (freq) {
4171 wpa_printf(MSG_INFO,
4172 "TEST: Override OCI KDE frequency %d -> %u MHz",
4173 ci.frequency, freq);
4174 ci.frequency = freq;
4175 }
4176#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom74f70d42019-02-11 14:42:39 -08004177
4178 return ocv_insert_oci_kde(&ci, argpos);
4179#else /* CONFIG_OCV */
4180 return 0;
4181#endif /* CONFIG_OCV */
4182}
4183
4184
Hai Shalomfdcde762020-04-02 11:19:20 -07004185#ifdef CONFIG_TESTING_OPTIONS
4186static u8 * replace_ie(const char *name, const u8 *old_buf, size_t *len, u8 eid,
4187 const u8 *ie, size_t ie_len)
4188{
4189 const u8 *elem;
4190 u8 *buf;
4191
4192 wpa_printf(MSG_DEBUG, "TESTING: %s EAPOL override", name);
4193 wpa_hexdump(MSG_DEBUG, "TESTING: wpa_ie before override",
4194 old_buf, *len);
4195 buf = os_malloc(*len + ie_len);
4196 if (!buf)
4197 return NULL;
4198 os_memcpy(buf, old_buf, *len);
4199 elem = get_ie(buf, *len, eid);
4200 if (elem) {
4201 u8 elem_len = 2 + elem[1];
4202
4203 os_memmove((void *) elem, elem + elem_len,
4204 *len - (elem - buf) - elem_len);
4205 *len -= elem_len;
4206 }
4207 os_memcpy(buf + *len, ie, ie_len);
4208 *len += ie_len;
4209 wpa_hexdump(MSG_DEBUG, "TESTING: wpa_ie after EAPOL override",
4210 buf, *len);
4211
4212 return buf;
4213}
4214#endif /* CONFIG_TESTING_OPTIONS */
4215
4216
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004217#ifdef CONFIG_IEEE80211BE
4218
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004219void wpa_auth_ml_get_key_info(struct wpa_authenticator *a,
4220 struct wpa_auth_ml_link_key_info *info,
Sunil Ravic0f5d412024-09-11 22:12:49 +00004221 bool mgmt_frame_prot, bool beacon_prot,
4222 bool rekey)
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004223{
4224 struct wpa_group *gsm = a->group;
4225 u8 rsc[WPA_KEY_RSC_LEN];
4226
4227 wpa_printf(MSG_DEBUG,
4228 "MLD: Get group key info: link_id=%u, IGTK=%u, BIGTK=%u",
4229 info->link_id, mgmt_frame_prot, beacon_prot);
4230
4231 info->gtkidx = gsm->GN & 0x03;
4232 info->gtk = gsm->GTK[gsm->GN - 1];
4233 info->gtk_len = gsm->GTK_len;
4234
Sunil Ravic0f5d412024-09-11 22:12:49 +00004235 if (rekey || wpa_auth_get_seqnum(a, NULL, gsm->GN, rsc) < 0)
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004236 os_memset(info->pn, 0, sizeof(info->pn));
4237 else
4238 os_memcpy(info->pn, rsc, sizeof(info->pn));
4239
4240 if (!mgmt_frame_prot)
4241 return;
4242
4243 info->igtkidx = gsm->GN_igtk;
4244 info->igtk = gsm->IGTK[gsm->GN_igtk - 4];
4245 info->igtk_len = wpa_cipher_key_len(a->conf.group_mgmt_cipher);
4246
Sunil Ravic0f5d412024-09-11 22:12:49 +00004247 if (rekey || wpa_auth_get_seqnum(a, NULL, gsm->GN_igtk, rsc) < 0)
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004248 os_memset(info->ipn, 0, sizeof(info->ipn));
4249 else
4250 os_memcpy(info->ipn, rsc, sizeof(info->ipn));
4251
4252 if (!beacon_prot)
4253 return;
4254
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004255 if (a->conf.tx_bss_auth) {
4256 a = a->conf.tx_bss_auth;
4257 gsm = a->group;
4258 }
4259
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004260 info->bigtkidx = gsm->GN_bigtk;
4261 info->bigtk = gsm->BIGTK[gsm->GN_bigtk - 6];
4262
Sunil Ravic0f5d412024-09-11 22:12:49 +00004263 if (rekey || wpa_auth_get_seqnum(a, NULL, gsm->GN_bigtk, rsc) < 0)
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004264 os_memset(info->bipn, 0, sizeof(info->bipn));
4265 else
4266 os_memcpy(info->bipn, rsc, sizeof(info->bipn));
4267}
4268
4269
4270static void wpa_auth_get_ml_key_info(struct wpa_authenticator *wpa_auth,
Sunil Ravic0f5d412024-09-11 22:12:49 +00004271 struct wpa_auth_ml_key_info *info,
4272 bool rekey)
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004273{
4274 if (!wpa_auth->cb->get_ml_key_info)
4275 return;
4276
Sunil Ravic0f5d412024-09-11 22:12:49 +00004277 wpa_auth->cb->get_ml_key_info(wpa_auth->cb_ctx, info, rekey);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004278}
4279
4280
4281static size_t wpa_auth_ml_group_kdes_len(struct wpa_state_machine *sm)
4282{
Sunil Ravi7f769292024-07-23 22:21:32 +00004283 struct wpa_authenticator *wpa_auth;
4284 size_t kde_len = 0;
4285 int link_id;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004286
4287 if (sm->mld_assoc_link_id < 0)
4288 return 0;
4289
Sunil Ravi7f769292024-07-23 22:21:32 +00004290 for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
4291 if (!sm->mld_links[link_id].valid)
4292 continue;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004293
Sunil Ravi7f769292024-07-23 22:21:32 +00004294 wpa_auth = sm->mld_links[link_id].wpa_auth;
4295 if (!wpa_auth || !wpa_auth->group)
4296 continue;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004297
Sunil Ravi7f769292024-07-23 22:21:32 +00004298 /* MLO GTK KDE
4299 * Header + Key ID + Tx + LinkID + PN + GTK */
4300 kde_len += KDE_HDR_LEN + 1 + RSN_PN_LEN;
4301 kde_len += wpa_auth->group->GTK_len;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004302
Sunil Ravi7f769292024-07-23 22:21:32 +00004303 if (!sm->mgmt_frame_prot)
4304 continue;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004305
Sunil Ravi7f769292024-07-23 22:21:32 +00004306 if (wpa_auth->conf.tx_bss_auth)
4307 wpa_auth = wpa_auth->conf.tx_bss_auth;
4308
4309 /* MLO IGTK KDE
4310 * Header + Key ID + IPN + LinkID + IGTK */
4311 kde_len += KDE_HDR_LEN + WPA_IGTK_KDE_PREFIX_LEN + 1;
4312 kde_len += wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher);
4313
4314 if (!wpa_auth->conf.beacon_prot)
4315 continue;
4316
4317 /* MLO BIGTK KDE
4318 * Header + Key ID + BIPN + LinkID + BIGTK */
4319 kde_len += KDE_HDR_LEN + WPA_BIGTK_KDE_PREFIX_LEN + 1;
4320 kde_len += wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004321 }
4322
Sunil Ravi7f769292024-07-23 22:21:32 +00004323 wpa_printf(MSG_DEBUG, "MLO Group KDEs len = %zu", kde_len);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004324
4325 return kde_len;
4326}
4327
4328
4329static u8 * wpa_auth_ml_group_kdes(struct wpa_state_machine *sm, u8 *pos)
4330{
4331 struct wpa_auth_ml_key_info ml_key_info;
4332 unsigned int i, link_id;
Sunil Ravi7f769292024-07-23 22:21:32 +00004333 u8 *start = pos;
Sunil Ravic0f5d412024-09-11 22:12:49 +00004334 bool rekey = sm->wpa_ptk_group_state == WPA_PTK_GROUP_REKEYNEGOTIATING;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004335
4336 /* First fetch the key information from all the authenticators */
4337 os_memset(&ml_key_info, 0, sizeof(ml_key_info));
4338 ml_key_info.n_mld_links = sm->n_mld_affiliated_links + 1;
4339
4340 /*
4341 * Assume that management frame protection and beacon protection are the
4342 * same on all links.
4343 */
4344 ml_key_info.mgmt_frame_prot = sm->mgmt_frame_prot;
4345 ml_key_info.beacon_prot = sm->wpa_auth->conf.beacon_prot;
4346
4347 for (i = 0, link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
4348 if (!sm->mld_links[link_id].valid)
4349 continue;
4350
4351 ml_key_info.links[i++].link_id = link_id;
4352 }
4353
Sunil Ravic0f5d412024-09-11 22:12:49 +00004354 wpa_auth_get_ml_key_info(sm->wpa_auth, &ml_key_info, rekey);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004355
4356 /* Add MLO GTK KDEs */
4357 for (i = 0, link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004358 if (!sm->mld_links[link_id].valid ||
4359 !ml_key_info.links[i].gtk_len)
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004360 continue;
4361
4362 wpa_printf(MSG_DEBUG, "RSN: MLO GTK: link=%u", link_id);
4363 wpa_hexdump_key(MSG_DEBUG, "RSN: MLO GTK",
4364 ml_key_info.links[i].gtk,
4365 ml_key_info.links[i].gtk_len);
4366
4367 *pos++ = WLAN_EID_VENDOR_SPECIFIC;
4368 *pos++ = RSN_SELECTOR_LEN + 1 + 6 +
4369 ml_key_info.links[i].gtk_len;
4370
4371 RSN_SELECTOR_PUT(pos, RSN_KEY_DATA_MLO_GTK);
4372 pos += RSN_SELECTOR_LEN;
4373
4374 *pos++ = (ml_key_info.links[i].gtkidx & 0x3) | (link_id << 4);
4375
4376 os_memcpy(pos, ml_key_info.links[i].pn, 6);
4377 pos += 6;
4378
4379 os_memcpy(pos, ml_key_info.links[i].gtk,
4380 ml_key_info.links[i].gtk_len);
4381 pos += ml_key_info.links[i].gtk_len;
4382
4383 i++;
4384 }
4385
Sunil Ravi7f769292024-07-23 22:21:32 +00004386 if (!sm->mgmt_frame_prot) {
4387 wpa_printf(MSG_DEBUG, "RSN: MLO Group KDE len = %ld",
4388 pos - start);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004389 return pos;
Sunil Ravi7f769292024-07-23 22:21:32 +00004390 }
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004391
4392 /* Add MLO IGTK KDEs */
4393 for (i = 0, link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004394 if (!sm->mld_links[link_id].valid ||
4395 !ml_key_info.links[i].igtk_len)
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004396 continue;
4397
4398 wpa_printf(MSG_DEBUG, "RSN: MLO IGTK: link=%u", link_id);
4399 wpa_hexdump_key(MSG_DEBUG, "RSN: MLO IGTK",
4400 ml_key_info.links[i].igtk,
4401 ml_key_info.links[i].igtk_len);
4402
4403 *pos++ = WLAN_EID_VENDOR_SPECIFIC;
4404 *pos++ = RSN_SELECTOR_LEN + 2 + 1 +
4405 sizeof(ml_key_info.links[i].ipn) +
4406 ml_key_info.links[i].igtk_len;
4407
4408 RSN_SELECTOR_PUT(pos, RSN_KEY_DATA_MLO_IGTK);
4409 pos += RSN_SELECTOR_LEN;
4410
4411 /* Add the Key ID */
4412 *pos++ = ml_key_info.links[i].igtkidx;
4413 *pos++ = 0;
4414
4415 /* Add the IPN */
4416 os_memcpy(pos, ml_key_info.links[i].ipn,
4417 sizeof(ml_key_info.links[i].ipn));
4418 pos += sizeof(ml_key_info.links[i].ipn);
4419
4420 *pos++ = ml_key_info.links[i].link_id << 4;
4421
4422 os_memcpy(pos, ml_key_info.links[i].igtk,
4423 ml_key_info.links[i].igtk_len);
4424 pos += ml_key_info.links[i].igtk_len;
4425
4426 i++;
4427 }
4428
Sunil Ravi7f769292024-07-23 22:21:32 +00004429 if (!sm->wpa_auth->conf.beacon_prot) {
4430 wpa_printf(MSG_DEBUG, "RSN: MLO Group KDE len = %ld",
4431 pos - start);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004432 return pos;
Sunil Ravi7f769292024-07-23 22:21:32 +00004433 }
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004434
4435 /* Add MLO BIGTK KDEs */
4436 for (i = 0, link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004437 if (!sm->mld_links[link_id].valid ||
4438 !ml_key_info.links[i].bigtk ||
4439 !ml_key_info.links[i].igtk_len)
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004440 continue;
4441
4442 wpa_printf(MSG_DEBUG, "RSN: MLO BIGTK: link=%u", link_id);
4443 wpa_hexdump_key(MSG_DEBUG, "RSN: MLO BIGTK",
4444 ml_key_info.links[i].bigtk,
4445 ml_key_info.links[i].igtk_len);
4446
4447 *pos++ = WLAN_EID_VENDOR_SPECIFIC;
4448 *pos++ = RSN_SELECTOR_LEN + 2 + 1 +
4449 sizeof(ml_key_info.links[i].bipn) +
4450 ml_key_info.links[i].igtk_len;
4451
4452 RSN_SELECTOR_PUT(pos, RSN_KEY_DATA_MLO_BIGTK);
4453 pos += RSN_SELECTOR_LEN;
4454
4455 /* Add the Key ID */
4456 *pos++ = ml_key_info.links[i].bigtkidx;
4457 *pos++ = 0;
4458
4459 /* Add the BIPN */
4460 os_memcpy(pos, ml_key_info.links[i].bipn,
4461 sizeof(ml_key_info.links[i].bipn));
4462 pos += sizeof(ml_key_info.links[i].bipn);
4463
4464 *pos++ = ml_key_info.links[i].link_id << 4;
4465
4466 os_memcpy(pos, ml_key_info.links[i].bigtk,
4467 ml_key_info.links[i].igtk_len);
4468 pos += ml_key_info.links[i].igtk_len;
4469
4470 i++;
4471 }
4472
Sunil Ravi7f769292024-07-23 22:21:32 +00004473 wpa_printf(MSG_DEBUG, "RSN: MLO Group KDE len = %ld", pos - start);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004474 return pos;
4475}
4476
4477#endif /* CONFIG_IEEE80211BE */
4478
4479
4480static size_t wpa_auth_ml_kdes_len(struct wpa_state_machine *sm)
4481{
4482 size_t kde_len = 0;
4483
4484#ifdef CONFIG_IEEE80211BE
4485 unsigned int link_id;
4486
4487 if (sm->mld_assoc_link_id < 0)
4488 return 0;
4489
4490 /* For the MAC Address KDE */
4491 kde_len = 2 + RSN_SELECTOR_LEN + ETH_ALEN;
4492
Sunil Ravic0f5d412024-09-11 22:12:49 +00004493 /* MLO Link KDE and RSN Override Link KDE for each link */
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004494 for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
Sunil Ravi7f769292024-07-23 22:21:32 +00004495 struct wpa_authenticator *wpa_auth;
Sunil Ravic0f5d412024-09-11 22:12:49 +00004496 const u8 *ie;
Sunil Ravi7f769292024-07-23 22:21:32 +00004497
4498 wpa_auth = wpa_get_link_auth(sm->wpa_auth, link_id);
4499 if (!wpa_auth)
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004500 continue;
4501
Sunil Ravic0f5d412024-09-11 22:12:49 +00004502 /* MLO Link KDE */
Sunil Ravi7f769292024-07-23 22:21:32 +00004503 kde_len += 2 + RSN_SELECTOR_LEN + 1 + ETH_ALEN;
Sunil Ravic0f5d412024-09-11 22:12:49 +00004504
Sunil Ravi7f769292024-07-23 22:21:32 +00004505 ie = get_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
4506 WLAN_EID_RSN);
Sunil Ravic0f5d412024-09-11 22:12:49 +00004507 if (ie)
Sunil Ravi7f769292024-07-23 22:21:32 +00004508 kde_len += 2 + ie[1];
4509
4510 ie = get_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
4511 WLAN_EID_RSNX);
Sunil Ravic0f5d412024-09-11 22:12:49 +00004512 if (ie)
4513 kde_len += 2 + ie[1];
4514
4515 if (!rsn_is_snonce_cookie(sm->SNonce))
4516 continue;
4517
4518 /* RSN Override Link KDE */
4519 kde_len += 2 + RSN_SELECTOR_LEN + 1;
4520
4521 ie = get_vendor_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
4522 RSNE_OVERRIDE_IE_VENDOR_TYPE);
4523 if (ie)
4524 kde_len += 2 + ie[1];
4525
4526 ie = get_vendor_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
4527 RSNE_OVERRIDE_2_IE_VENDOR_TYPE);
4528 if (ie)
4529 kde_len += 2 + ie[1];
4530
4531 ie = get_vendor_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
4532 RSNXE_OVERRIDE_IE_VENDOR_TYPE);
4533 if (ie)
Sunil Ravi7f769292024-07-23 22:21:32 +00004534 kde_len += 2 + ie[1];
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004535 }
4536
4537 kde_len += wpa_auth_ml_group_kdes_len(sm);
4538#endif /* CONFIG_IEEE80211BE */
4539
4540 return kde_len;
4541}
4542
4543
4544static u8 * wpa_auth_ml_kdes(struct wpa_state_machine *sm, u8 *pos)
4545{
4546#ifdef CONFIG_IEEE80211BE
4547 u8 link_id;
Sunil Ravi7f769292024-07-23 22:21:32 +00004548 u8 *start = pos;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004549
4550 if (sm->mld_assoc_link_id < 0)
4551 return pos;
4552
4553 wpa_printf(MSG_DEBUG, "RSN: MLD: Adding MAC Address KDE");
4554 pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR,
Sunil Ravi7f769292024-07-23 22:21:32 +00004555 sm->wpa_auth->mld_addr, ETH_ALEN, NULL, 0);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004556
4557 for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
Sunil Ravi7f769292024-07-23 22:21:32 +00004558 struct wpa_authenticator *wpa_auth;
Sunil Ravic0f5d412024-09-11 22:12:49 +00004559 const u8 *rsne, *rsnxe, *rsnoe, *rsno2e, *rsnxoe;
4560 size_t rsne_len, rsnxe_len, rsnoe_len, rsno2e_len, rsnxoe_len;
4561 size_t kde_len;
Sunil Ravi7f769292024-07-23 22:21:32 +00004562
4563 wpa_auth = wpa_get_link_auth(sm->wpa_auth, link_id);
4564 if (!wpa_auth)
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004565 continue;
4566
Sunil Ravi7f769292024-07-23 22:21:32 +00004567 rsne = get_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
4568 WLAN_EID_RSN);
4569 rsne_len = rsne ? 2 + rsne[1] : 0;
Sunil Ravi7f769292024-07-23 22:21:32 +00004570
4571 rsnxe = get_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
4572 WLAN_EID_RSNX);
4573 rsnxe_len = rsnxe ? 2 + rsnxe[1] : 0;
Sunil Ravi7f769292024-07-23 22:21:32 +00004574
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004575 wpa_printf(MSG_DEBUG,
4576 "RSN: MLO Link: link=%u, len=%zu", link_id,
4577 RSN_SELECTOR_LEN + 1 + ETH_ALEN +
Sunil Ravi7f769292024-07-23 22:21:32 +00004578 rsne_len + rsnxe_len);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004579
Sunil Ravic0f5d412024-09-11 22:12:49 +00004580 /* MLO Link KDE */
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004581 *pos++ = WLAN_EID_VENDOR_SPECIFIC;
4582 *pos++ = RSN_SELECTOR_LEN + 1 + ETH_ALEN +
Sunil Ravi7f769292024-07-23 22:21:32 +00004583 rsne_len + rsnxe_len;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004584
4585 RSN_SELECTOR_PUT(pos, RSN_KEY_DATA_MLO_LINK);
4586 pos += RSN_SELECTOR_LEN;
4587
4588 /* Add the Link Information */
4589 *pos = link_id;
Sunil Ravi7f769292024-07-23 22:21:32 +00004590 if (rsne_len)
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004591 *pos |= RSN_MLO_LINK_KDE_LI_RSNE_INFO;
Sunil Ravi7f769292024-07-23 22:21:32 +00004592 if (rsnxe_len)
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004593 *pos |= RSN_MLO_LINK_KDE_LI_RSNXE_INFO;
4594
4595 pos++;
Sunil Ravi7f769292024-07-23 22:21:32 +00004596 os_memcpy(pos, wpa_auth->addr, ETH_ALEN);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004597 pos += ETH_ALEN;
4598
Sunil Ravi7f769292024-07-23 22:21:32 +00004599 if (rsne_len) {
Sunil Ravic0f5d412024-09-11 22:12:49 +00004600 os_memcpy(pos, rsne, rsne_len);
4601 pos += rsne_len;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004602 }
4603
Sunil Ravi7f769292024-07-23 22:21:32 +00004604 if (rsnxe_len) {
Sunil Ravic0f5d412024-09-11 22:12:49 +00004605 os_memcpy(pos, rsnxe, rsnxe_len);
4606 pos += rsnxe_len;
4607 }
4608
4609 if (!rsn_is_snonce_cookie(sm->SNonce))
4610 continue;
4611
4612 rsnoe = get_vendor_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
4613 RSNE_OVERRIDE_IE_VENDOR_TYPE);
4614 rsnoe_len = rsnoe ? 2 + rsnoe[1] : 0;
4615
4616 rsno2e = get_vendor_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
4617 RSNE_OVERRIDE_2_IE_VENDOR_TYPE);
4618 rsno2e_len = rsno2e ? 2 + rsno2e[1] : 0;
4619
4620 rsnxoe = get_vendor_ie(wpa_auth->wpa_ie, wpa_auth->wpa_ie_len,
4621 RSNXE_OVERRIDE_IE_VENDOR_TYPE);
4622 rsnxoe_len = rsnxoe ? 2 + rsnxoe[1] : 0;
4623
4624 wpa_printf(MSG_DEBUG,
4625 "RSN: RSN Override Link KDE: link=%u, len=%zu",
4626 link_id, RSN_SELECTOR_LEN + rsnoe_len + rsno2e_len +
4627 rsnxoe_len);
4628
4629 /* RSN Override Link KDE */
4630 *pos++ = WLAN_EID_VENDOR_SPECIFIC;
4631 kde_len = RSN_SELECTOR_LEN + 1 + rsnoe_len + rsno2e_len +
4632 rsnxoe_len;
4633 if (kde_len > 255) {
4634 wpa_printf(MSG_ERROR,
4635 "RSN: RSNOE/RSNO2E/RSNXOE too long (KDE length %zu) to fit in RSN Override Link KDE for link %u",
4636 kde_len, link_id);
4637 return NULL;
4638 }
4639 *pos++ = kde_len;
4640
4641 RSN_SELECTOR_PUT(pos, WFA_KEY_DATA_RSN_OVERRIDE_LINK);
4642 pos += RSN_SELECTOR_LEN;
4643
4644 *pos++ = link_id;
4645
4646 if (rsnoe_len) {
4647 os_memcpy(pos, rsnoe, rsnoe_len);
4648 pos += rsnoe_len;
4649 }
4650
4651 if (rsno2e_len) {
4652 os_memcpy(pos, rsno2e, rsno2e_len);
4653 pos += rsno2e_len;
4654 }
4655
4656 if (rsnxoe_len) {
4657 os_memcpy(pos, rsnxoe, rsnxoe_len);
4658 pos += rsnxoe_len;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004659 }
4660 }
4661
Sunil Ravic0f5d412024-09-11 22:12:49 +00004662 wpa_printf(MSG_DEBUG,
4663 "RSN: MLO Link KDEs and RSN Override Link KDEs len = %ld",
4664 pos - start);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004665 pos = wpa_auth_ml_group_kdes(sm, pos);
4666#endif /* CONFIG_IEEE80211BE */
4667
4668 return pos;
4669}
4670
4671
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004672SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
4673{
Hai Shaloma20dcd72022-02-04 13:43:00 -08004674 u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde = NULL, *pos, stub_gtk[32];
Sunil Ravia04bd252022-05-02 22:54:18 -07004675 size_t gtk_len, kde_len = 0, wpa_ie_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004676 struct wpa_group *gsm = sm->group;
4677 u8 *wpa_ie;
Hai Shalomfdcde762020-04-02 11:19:20 -07004678 int secure, gtkidx, encr = 0;
Sunil Ravi7f769292024-07-23 22:21:32 +00004679 u8 *wpa_ie_buf = NULL, *wpa_ie_buf2 = NULL, *wpa_ie_buf3 = NULL;
Hai Shalomfdcde762020-04-02 11:19:20 -07004680 u8 hdr[2];
4681 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004682#ifdef CONFIG_IEEE80211BE
4683 bool is_mld = sm->mld_assoc_link_id >= 0;
4684#else /* CONFIG_IEEE80211BE */
4685 bool is_mld = false;
4686#endif /* CONFIG_IEEE80211BE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004687
4688 SM_ENTRY_MA(WPA_PTK, PTKINITNEGOTIATING, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07004689 sm->TimeoutEvt = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004690
4691 sm->TimeoutCtr++;
Hai Shalomfdcde762020-04-02 11:19:20 -07004692 if (conf->wpa_disable_eapol_key_retries && sm->TimeoutCtr > 1) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004693 /* Do not allow retransmission of EAPOL-Key msg 3/4 */
4694 return;
4695 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004696 if (sm->TimeoutCtr > conf->wpa_pairwise_update_count) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004697 /* No point in sending the EAPOL-Key - we will disconnect
4698 * immediately following this. */
4699 return;
4700 }
4701
4702 /* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, [MDIE],
Hai Shalomfdcde762020-04-02 11:19:20 -07004703 GTK[GN], IGTK, [BIGTK], [FTIE], [TIE * 2])
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004704 */
4705 os_memset(rsc, 0, WPA_KEY_RSC_LEN);
4706 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc);
4707 /* If FT is used, wpa_auth->wpa_ie includes both RSNIE and MDIE */
4708 wpa_ie = sm->wpa_auth->wpa_ie;
4709 wpa_ie_len = sm->wpa_auth->wpa_ie_len;
Hai Shalomfdcde762020-04-02 11:19:20 -07004710 if (sm->wpa == WPA_VERSION_WPA && (conf->wpa & WPA_PROTO_RSN) &&
4711 wpa_ie_len > wpa_ie[1] + 2U && wpa_ie[0] == WLAN_EID_RSN) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004712 /* WPA-only STA, remove RSN IE and possible MDIE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004713 wpa_ie = wpa_ie + wpa_ie[1] + 2;
Hai Shalom60840252021-02-19 19:02:11 -08004714 if (wpa_ie[0] == WLAN_EID_RSNX)
4715 wpa_ie = wpa_ie + wpa_ie[1] + 2;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004716 if (wpa_ie[0] == WLAN_EID_MOBILITY_DOMAIN)
4717 wpa_ie = wpa_ie + wpa_ie[1] + 2;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004718 wpa_ie_len = wpa_ie[1] + 2;
4719 }
Sunil Ravic0f5d412024-09-11 22:12:49 +00004720 if ((conf->rsn_override_key_mgmt || conf->rsn_override_key_mgmt_2) &&
4721 !rsn_is_snonce_cookie(sm->SNonce)) {
4722 u8 *ie;
4723 size_t ie_len;
4724 u32 ids[] = {
4725 RSNE_OVERRIDE_IE_VENDOR_TYPE,
4726 RSNE_OVERRIDE_2_IE_VENDOR_TYPE,
4727 RSNXE_OVERRIDE_IE_VENDOR_TYPE,
4728 0
4729 };
4730 int i;
Sunil Ravi7f769292024-07-23 22:21:32 +00004731
4732 wpa_printf(MSG_DEBUG,
Sunil Ravic0f5d412024-09-11 22:12:49 +00004733 "RSN: Remove RSNE/RSNXE override elements");
Sunil Ravi7f769292024-07-23 22:21:32 +00004734 wpa_hexdump(MSG_DEBUG, "EAPOL-Key msg 3/4 IEs before edits",
4735 wpa_ie, wpa_ie_len);
Sunil Ravic0f5d412024-09-11 22:12:49 +00004736 wpa_ie_buf3 = os_memdup(wpa_ie, wpa_ie_len);
Sunil Ravi7f769292024-07-23 22:21:32 +00004737 if (!wpa_ie_buf3)
4738 goto done;
Sunil Ravi7f769292024-07-23 22:21:32 +00004739 wpa_ie = wpa_ie_buf3;
Sunil Ravic0f5d412024-09-11 22:12:49 +00004740
4741 for (i = 0; ids[i]; i++) {
4742 ie = (u8 *) get_vendor_ie(wpa_ie, wpa_ie_len, ids[i]);
4743 if (ie) {
4744 ie_len = 2 + ie[1];
4745 os_memmove(ie, ie + ie_len,
4746 wpa_ie_len - (ie + ie_len - wpa_ie));
4747 wpa_ie_len -= ie_len;
4748 }
4749 }
Sunil Ravi7f769292024-07-23 22:21:32 +00004750 wpa_hexdump(MSG_DEBUG, "EAPOL-Key msg 3/4 IEs after edits",
4751 wpa_ie, wpa_ie_len);
4752 }
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004753#ifdef CONFIG_TESTING_OPTIONS
Hai Shalomfdcde762020-04-02 11:19:20 -07004754 if (conf->rsne_override_eapol_set) {
4755 wpa_ie_buf2 = replace_ie(
4756 "RSNE", wpa_ie, &wpa_ie_len, WLAN_EID_RSN,
4757 conf->rsne_override_eapol,
4758 conf->rsne_override_eapol_len);
4759 if (!wpa_ie_buf2)
4760 goto done;
4761 wpa_ie = wpa_ie_buf2;
4762 }
4763 if (conf->rsnxe_override_eapol_set) {
4764 wpa_ie_buf = replace_ie(
4765 "RSNXE", wpa_ie, &wpa_ie_len, WLAN_EID_RSNX,
4766 conf->rsnxe_override_eapol,
4767 conf->rsnxe_override_eapol_len);
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004768 if (!wpa_ie_buf)
Hai Shalomfdcde762020-04-02 11:19:20 -07004769 goto done;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004770 wpa_ie = wpa_ie_buf;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004771 }
4772#endif /* CONFIG_TESTING_OPTIONS */
Sunil Raviaf8751c2023-03-29 11:35:17 -07004773 wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004774 "sending 3/4 msg of 4-Way Handshake");
4775 if (sm->wpa == WPA_VERSION_WPA2) {
Hai Shalomfdcde762020-04-02 11:19:20 -07004776 if (sm->use_ext_key_id && sm->TimeoutCtr == 1 &&
4777 wpa_auth_set_key(sm->wpa_auth, 0,
4778 wpa_cipher_to_alg(sm->pairwise),
4779 sm->addr,
4780 sm->keyidx_active, sm->PTK.tk,
4781 wpa_cipher_key_len(sm->pairwise),
4782 KEY_FLAG_PAIRWISE_RX)) {
4783 wpa_sta_disconnect(sm->wpa_auth, sm->addr,
4784 WLAN_REASON_PREV_AUTH_NOT_VALID);
4785 return;
4786 }
4787
Sunil Ravi89eba102022-09-13 21:04:37 -07004788#ifdef CONFIG_PASN
4789 if (sm->wpa_auth->conf.secure_ltf &&
4790 ieee802_11_rsnx_capab(sm->rsnxe,
4791 WLAN_RSNX_CAPAB_SECURE_LTF) &&
4792 wpa_auth_set_ltf_keyseed(sm->wpa_auth, sm->addr,
4793 sm->PTK.ltf_keyseed,
4794 sm->PTK.ltf_keyseed_len)) {
4795 wpa_printf(MSG_ERROR,
4796 "WPA: Failed to set LTF keyseed to driver");
4797 wpa_sta_disconnect(sm->wpa_auth, sm->addr,
4798 WLAN_REASON_PREV_AUTH_NOT_VALID);
4799 return;
4800 }
4801#endif /* CONFIG_PASN */
4802
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004803 /* WPA2 send GTK in the 4-way handshake */
4804 secure = 1;
4805 gtk = gsm->GTK[gsm->GN - 1];
4806 gtk_len = gsm->GTK_len;
Hai Shalomfdcde762020-04-02 11:19:20 -07004807 if (conf->disable_gtk ||
Roshan Pius3a1667e2018-07-03 15:17:14 -07004808 sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004809 /*
4810 * Provide unique random GTK to each STA to prevent use
4811 * of GTK in the BSS.
4812 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08004813 if (random_get_bytes(stub_gtk, gtk_len) < 0)
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004814 goto done;
Hai Shaloma20dcd72022-02-04 13:43:00 -08004815 gtk = stub_gtk;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004816 }
Hai Shalomc3565922019-10-28 11:58:20 -07004817 gtkidx = gsm->GN;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004818 _rsc = rsc;
4819 encr = 1;
4820 } else {
4821 /* WPA does not include GTK in msg 3/4 */
4822 secure = 0;
4823 gtk = NULL;
4824 gtk_len = 0;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004825 gtkidx = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004826 _rsc = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004827 if (sm->rx_eapol_key_secure) {
4828 /*
4829 * It looks like Windows 7 supplicant tries to use
4830 * Secure bit in msg 2/4 after having reported Michael
4831 * MIC failure and it then rejects the 4-way handshake
4832 * if msg 3/4 does not set Secure bit. Work around this
4833 * by setting the Secure bit here even in the case of
4834 * WPA if the supplicant used it first.
4835 */
Sunil Raviaf8751c2023-03-29 11:35:17 -07004836 wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm),
4837 LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07004838 "STA used Secure bit in WPA msg 2/4 - set Secure for 3/4 as workaround");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004839 secure = 1;
4840 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004841 }
4842
Hai Shalom74f70d42019-02-11 14:42:39 -08004843 kde_len = wpa_ie_len + ieee80211w_kde_len(sm) + ocv_oci_len(sm);
Hai Shalomfdcde762020-04-02 11:19:20 -07004844
4845 if (sm->use_ext_key_id)
4846 kde_len += 2 + RSN_SELECTOR_LEN + 2;
4847
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004848 if (gtk)
4849 kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004850#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004851 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
4852 kde_len += 2 + PMKID_LEN; /* PMKR1Name into RSN IE */
4853 kde_len += 300; /* FTIE + 2 * TIE */
4854 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004855#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08004856#ifdef CONFIG_P2P
4857 if (WPA_GET_BE32(sm->ip_addr) > 0)
4858 kde_len += 2 + RSN_SELECTOR_LEN + 3 * 4;
4859#endif /* CONFIG_P2P */
Hai Shalomfdcde762020-04-02 11:19:20 -07004860
4861 if (conf->transition_disable)
4862 kde_len += 2 + RSN_SELECTOR_LEN + 1;
4863
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004864#ifdef CONFIG_DPP2
4865 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP)
4866 kde_len += 2 + RSN_SELECTOR_LEN + 2;
4867#endif /* CONFIG_DPP2 */
4868
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004869 kde_len += wpa_auth_ml_kdes_len(sm);
4870
Sunil Ravi7f769292024-07-23 22:21:32 +00004871 if (sm->ssid_protection)
4872 kde_len += 2 + conf->ssid_len;
4873
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004874#ifdef CONFIG_TESTING_OPTIONS
4875 if (conf->eapol_m3_elements)
4876 kde_len += wpabuf_len(conf->eapol_m3_elements);
4877#endif /* CONFIG_TESTING_OPTIONS */
4878
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004879 kde = os_malloc(kde_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07004880 if (!kde)
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004881 goto done;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004882
4883 pos = kde;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004884 if (!is_mld) {
4885 os_memcpy(pos, wpa_ie, wpa_ie_len);
4886 pos += wpa_ie_len;
4887 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004888#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004889 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08004890 int res;
4891 size_t elen;
4892
4893 elen = pos - kde;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004894 res = wpa_insert_pmkid(kde, &elen, sm->pmk_r1_name, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004895 if (res < 0) {
Hai Shalomfdcde762020-04-02 11:19:20 -07004896 wpa_printf(MSG_ERROR,
4897 "FT: Failed to insert PMKR1Name into RSN IE in EAPOL-Key data");
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004898 goto done;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004899 }
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08004900 pos -= wpa_ie_len;
4901 pos += elen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004902 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004903#endif /* CONFIG_IEEE80211R_AP */
Hai Shalomfdcde762020-04-02 11:19:20 -07004904 hdr[1] = 0;
4905
4906 if (sm->use_ext_key_id) {
4907 hdr[0] = sm->keyidx_active & 0x01;
4908 pos = wpa_add_kde(pos, RSN_KEY_DATA_KEYID, hdr, 2, NULL, 0);
4909 }
4910
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004911 if (gtk && !is_mld) {
Hai Shalomc3565922019-10-28 11:58:20 -07004912 hdr[0] = gtkidx & 0x03;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004913 pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
4914 gtk, gtk_len);
4915 }
4916 pos = ieee80211w_kde_add(sm, pos);
Hai Shalom899fcc72020-10-19 14:38:18 -07004917 if (ocv_oci_add(sm, &pos, conf->oci_freq_override_eapol_m3) < 0)
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004918 goto done;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004919
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004920#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004921 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
4922 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004923
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08004924 if (sm->assoc_resp_ftie &&
4925 kde + kde_len - pos >= 2 + sm->assoc_resp_ftie[1]) {
4926 os_memcpy(pos, sm->assoc_resp_ftie,
4927 2 + sm->assoc_resp_ftie[1]);
4928 res = 2 + sm->assoc_resp_ftie[1];
4929 } else {
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00004930 res = wpa_write_ftie(conf, sm->wpa_key_mgmt,
4931 sm->xxkey_len,
Roshan Pius3a1667e2018-07-03 15:17:14 -07004932 conf->r0_key_holder,
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08004933 conf->r0_key_holder_len,
4934 NULL, NULL, pos,
4935 kde + kde_len - pos,
Hai Shalomfdcde762020-04-02 11:19:20 -07004936 NULL, 0, 0);
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08004937 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004938 if (res < 0) {
Hai Shalomfdcde762020-04-02 11:19:20 -07004939 wpa_printf(MSG_ERROR,
4940 "FT: Failed to insert FTIE into EAPOL-Key Key Data");
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004941 goto done;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004942 }
4943 pos += res;
4944
4945 /* TIE[ReassociationDeadline] (TU) */
4946 *pos++ = WLAN_EID_TIMEOUT_INTERVAL;
4947 *pos++ = 5;
4948 *pos++ = WLAN_TIMEOUT_REASSOC_DEADLINE;
4949 WPA_PUT_LE32(pos, conf->reassociation_deadline);
4950 pos += 4;
4951
4952 /* TIE[KeyLifetime] (seconds) */
4953 *pos++ = WLAN_EID_TIMEOUT_INTERVAL;
4954 *pos++ = 5;
4955 *pos++ = WLAN_TIMEOUT_KEY_LIFETIME;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004956 WPA_PUT_LE32(pos, conf->r0_key_lifetime);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004957 pos += 4;
4958 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004959#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08004960#ifdef CONFIG_P2P
4961 if (WPA_GET_BE32(sm->ip_addr) > 0) {
4962 u8 addr[3 * 4];
4963 os_memcpy(addr, sm->ip_addr, 4);
Hai Shalomfdcde762020-04-02 11:19:20 -07004964 os_memcpy(addr + 4, conf->ip_addr_mask, 4);
4965 os_memcpy(addr + 8, conf->ip_addr_go, 4);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08004966 pos = wpa_add_kde(pos, WFA_KEY_DATA_IP_ADDR_ALLOC,
4967 addr, sizeof(addr), NULL, 0);
4968 }
4969#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004970
Hai Shalomfdcde762020-04-02 11:19:20 -07004971 if (conf->transition_disable)
4972 pos = wpa_add_kde(pos, WFA_KEY_DATA_TRANSITION_DISABLE,
4973 &conf->transition_disable, 1, NULL, 0);
4974
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004975#ifdef CONFIG_DPP2
4976 if (DPP_VERSION > 1 && sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP) {
4977 u8 payload[2];
4978
4979 payload[0] = DPP_VERSION; /* Protocol Version */
4980 payload[1] = 0; /* Flags */
4981 if (conf->dpp_pfs == 0)
4982 payload[1] |= DPP_KDE_PFS_ALLOWED;
4983 else if (conf->dpp_pfs == 1)
4984 payload[1] |= DPP_KDE_PFS_ALLOWED |
4985 DPP_KDE_PFS_REQUIRED;
4986 pos = wpa_add_kde(pos, WFA_KEY_DATA_DPP,
4987 payload, sizeof(payload), NULL, 0);
4988 }
4989#endif /* CONFIG_DPP2 */
4990
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004991 pos = wpa_auth_ml_kdes(sm, pos);
Sunil Ravic0f5d412024-09-11 22:12:49 +00004992 if (!pos) {
4993 wpa_printf(MSG_ERROR, "RSN: Failed to add MLO KDEs");
4994 goto done;
4995 }
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004996
Sunil Ravi7f769292024-07-23 22:21:32 +00004997 if (sm->ssid_protection) {
4998 *pos++ = WLAN_EID_SSID;
4999 *pos++ = conf->ssid_len;
5000 os_memcpy(pos, conf->ssid, conf->ssid_len);
5001 pos += conf->ssid_len;
5002 }
5003
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005004#ifdef CONFIG_TESTING_OPTIONS
5005 if (conf->eapol_m3_elements) {
5006 os_memcpy(pos, wpabuf_head(conf->eapol_m3_elements),
5007 wpabuf_len(conf->eapol_m3_elements));
5008 pos += wpabuf_len(conf->eapol_m3_elements);
5009 }
5010
5011 if (conf->eapol_m3_no_encrypt)
5012 encr = 0;
5013#endif /* CONFIG_TESTING_OPTIONS */
5014
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005015 wpa_send_eapol(sm->wpa_auth, sm,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005016 (secure ? WPA_KEY_INFO_SECURE : 0) |
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005017 (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
5018 WPA_KEY_INFO_MIC : 0) |
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005019 WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL |
5020 WPA_KEY_INFO_KEY_TYPE,
Hai Shalomc3565922019-10-28 11:58:20 -07005021 _rsc, sm->ANonce, kde, pos - kde, 0, encr);
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08005022done:
Sunil Ravia04bd252022-05-02 22:54:18 -07005023 bin_clear_free(kde, kde_len);
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08005024 os_free(wpa_ie_buf);
Hai Shalomfdcde762020-04-02 11:19:20 -07005025 os_free(wpa_ie_buf2);
Sunil Ravi7f769292024-07-23 22:21:32 +00005026 os_free(wpa_ie_buf3);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005027}
5028
5029
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005030static int wpa_auth_validate_ml_kdes_m4(struct wpa_state_machine *sm)
5031{
5032#ifdef CONFIG_IEEE80211BE
5033 const struct ieee802_1x_hdr *hdr;
5034 const struct wpa_eapol_key *key;
5035 struct wpa_eapol_ie_parse kde;
5036 const u8 *key_data, *mic;
5037 u16 key_data_length;
5038 size_t mic_len;
5039
5040 if (sm->mld_assoc_link_id < 0)
5041 return 0;
5042
5043 /*
5044 * Note: last_rx_eapol_key length fields have already been validated in
5045 * wpa_receive().
5046 */
5047 mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
5048
5049 hdr = (const struct ieee802_1x_hdr *) sm->last_rx_eapol_key;
5050 key = (const struct wpa_eapol_key *) (hdr + 1);
5051 mic = (const u8 *) (key + 1);
5052 key_data = mic + mic_len + 2;
5053 key_data_length = WPA_GET_BE16(mic + mic_len);
5054 if (key_data_length > sm->last_rx_eapol_key_len - sizeof(*hdr) -
5055 sizeof(*key) - mic_len - 2)
5056 return -1;
5057
5058 if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) {
5059 wpa_auth_vlogger(sm->wpa_auth, wpa_auth_get_spa(sm),
5060 LOGGER_INFO,
5061 "received EAPOL-Key msg 4/4 with invalid Key Data contents");
5062 return -1;
5063 }
5064
5065 /* MLD MAC address must be the same */
5066 if (!kde.mac_addr ||
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005067 !ether_addr_equal(kde.mac_addr, sm->peer_mld_addr)) {
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005068 wpa_printf(MSG_DEBUG,
5069 "MLD: Mismatching or missing MLD address in EAPOL-Key msg 4/4");
5070 return -1;
5071 }
5072
5073 wpa_printf(MSG_DEBUG, "MLD: MLD address in EAPOL-Key msg 4/4: " MACSTR,
5074 MAC2STR(kde.mac_addr));
5075#endif /* CONFIG_IEEE80211BE */
5076
5077 return 0;
5078}
5079
5080
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005081SM_STATE(WPA_PTK, PTKINITDONE)
5082{
5083 SM_ENTRY_MA(WPA_PTK, PTKINITDONE, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07005084 sm->EAPOLKeyReceived = false;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005085
5086 if (wpa_auth_validate_ml_kdes_m4(sm) < 0) {
5087 wpa_sta_disconnect(sm->wpa_auth, sm->addr,
5088 WLAN_REASON_PREV_AUTH_NOT_VALID);
5089 return;
5090 }
5091
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005092 if (sm->Pair) {
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07005093 enum wpa_alg alg = wpa_cipher_to_alg(sm->pairwise);
5094 int klen = wpa_cipher_key_len(sm->pairwise);
Hai Shalomfdcde762020-04-02 11:19:20 -07005095 int res;
5096
5097 if (sm->use_ext_key_id)
5098 res = wpa_auth_set_key(sm->wpa_auth, 0, 0, sm->addr,
5099 sm->keyidx_active, NULL, 0,
5100 KEY_FLAG_PAIRWISE_RX_TX_MODIFY);
5101 else
5102 res = wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr,
5103 0, sm->PTK.tk, klen,
5104 KEY_FLAG_PAIRWISE_RX_TX);
5105 if (res) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005106 wpa_sta_disconnect(sm->wpa_auth, sm->addr,
5107 WLAN_REASON_PREV_AUTH_NOT_VALID);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005108 return;
5109 }
Sunil Ravi89eba102022-09-13 21:04:37 -07005110
5111#ifdef CONFIG_PASN
5112 if (sm->wpa_auth->conf.secure_ltf &&
5113 ieee802_11_rsnx_capab(sm->rsnxe,
5114 WLAN_RSNX_CAPAB_SECURE_LTF) &&
5115 wpa_auth_set_ltf_keyseed(sm->wpa_auth, sm->addr,
5116 sm->PTK.ltf_keyseed,
5117 sm->PTK.ltf_keyseed_len)) {
5118 wpa_printf(MSG_ERROR,
5119 "WPA: Failed to set LTF keyseed to driver");
5120 wpa_sta_disconnect(sm->wpa_auth, sm->addr,
5121 WLAN_REASON_PREV_AUTH_NOT_VALID);
5122 return;
5123 }
5124#endif /* CONFIG_PASN */
5125
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005126 /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */
Hai Shalome21d4e82020-04-29 16:34:06 -07005127 sm->pairwise_set = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005128
Hai Shalom81f62d82019-07-22 12:10:00 -07005129 wpa_auth_set_ptk_rekey_timer(sm);
Hai Shalom60840252021-02-19 19:02:11 -08005130 wpa_auth_store_ptksa(sm->wpa_auth, sm->addr, sm->pairwise,
5131 dot11RSNAConfigPMKLifetime, &sm->PTK);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005132
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005133 if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
5134 sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP ||
5135 sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005136 wpa_auth_set_eapol(sm->wpa_auth, sm->addr,
5137 WPA_EAPOL_authorized, 1);
5138 }
5139 }
5140
5141 if (0 /* IBSS == TRUE */) {
5142 sm->keycount++;
5143 if (sm->keycount == 2) {
5144 wpa_auth_set_eapol(sm->wpa_auth, sm->addr,
5145 WPA_EAPOL_portValid, 1);
5146 }
5147 } else {
5148 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid,
5149 1);
5150 }
Hai Shalome21d4e82020-04-29 16:34:06 -07005151 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyAvailable,
5152 false);
5153 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyDone, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005154 if (sm->wpa == WPA_VERSION_WPA)
Hai Shalome21d4e82020-04-29 16:34:06 -07005155 sm->PInitAKeys = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005156 else
Hai Shalome21d4e82020-04-29 16:34:06 -07005157 sm->has_GTK = true;
Sunil Raviaf8751c2023-03-29 11:35:17 -07005158 wpa_auth_vlogger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005159 "pairwise key handshake completed (%s)",
5160 sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN");
Hai Shaloma20dcd72022-02-04 13:43:00 -08005161 wpa_msg(sm->wpa_auth->conf.msg_ctx, MSG_INFO, "EAPOL-4WAY-HS-COMPLETED "
5162 MACSTR, MAC2STR(sm->addr));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005163
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005164#ifdef CONFIG_IEEE80211R_AP
Sunil Raviaf8751c2023-03-29 11:35:17 -07005165 wpa_ft_push_pmk_r1(sm->wpa_auth, wpa_auth_get_spa(sm));
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005166#endif /* CONFIG_IEEE80211R_AP */
Sunil Ravia04bd252022-05-02 22:54:18 -07005167
5168 sm->ptkstart_without_success = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005169}
5170
5171
5172SM_STEP(WPA_PTK)
5173{
5174 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
Hai Shalomfdcde762020-04-02 11:19:20 -07005175 struct wpa_auth_config *conf = &wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005176
5177 if (sm->Init)
5178 SM_ENTER(WPA_PTK, INITIALIZE);
5179 else if (sm->Disconnect
5180 /* || FIX: dot11RSNAConfigSALifetime timeout */) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07005181 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005182 "WPA_PTK: sm->Disconnect");
5183 SM_ENTER(WPA_PTK, DISCONNECT);
5184 }
5185 else if (sm->DeauthenticationRequest)
5186 SM_ENTER(WPA_PTK, DISCONNECTED);
5187 else if (sm->AuthenticationRequest)
5188 SM_ENTER(WPA_PTK, AUTHENTICATION);
5189 else if (sm->ReAuthenticationRequest)
5190 SM_ENTER(WPA_PTK, AUTHENTICATION2);
Jouni Malinen1420a892017-10-01 12:32:57 +03005191 else if (sm->PTKRequest) {
5192 if (wpa_auth_sm_ptk_update(sm) < 0)
5193 SM_ENTER(WPA_PTK, DISCONNECTED);
5194 else
5195 SM_ENTER(WPA_PTK, PTKSTART);
5196 } else switch (sm->wpa_ptk_state) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005197 case WPA_PTK_INITIALIZE:
5198 break;
5199 case WPA_PTK_DISCONNECT:
5200 SM_ENTER(WPA_PTK, DISCONNECTED);
5201 break;
5202 case WPA_PTK_DISCONNECTED:
5203 SM_ENTER(WPA_PTK, INITIALIZE);
5204 break;
5205 case WPA_PTK_AUTHENTICATION:
5206 SM_ENTER(WPA_PTK, AUTHENTICATION2);
5207 break;
5208 case WPA_PTK_AUTHENTICATION2:
5209 if (wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) &&
Hai Shalomfdcde762020-04-02 11:19:20 -07005210 wpa_auth_get_eapol(wpa_auth, sm->addr,
Hai Shalome21d4e82020-04-29 16:34:06 -07005211 WPA_EAPOL_keyRun))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005212 SM_ENTER(WPA_PTK, INITPMK);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005213 else if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
5214 sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005215 /* FIX: && 802.1X::keyRun */)
5216 SM_ENTER(WPA_PTK, INITPSK);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005217 else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP)
5218 SM_ENTER(WPA_PTK, INITPMK);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005219 break;
5220 case WPA_PTK_INITPMK:
Hai Shalomfdcde762020-04-02 11:19:20 -07005221 if (wpa_auth_get_eapol(wpa_auth, sm->addr,
Hai Shalome21d4e82020-04-29 16:34:06 -07005222 WPA_EAPOL_keyAvailable)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005223 SM_ENTER(WPA_PTK, PTKSTART);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005224#ifdef CONFIG_DPP
5225 } else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP && sm->pmksa) {
5226 SM_ENTER(WPA_PTK, PTKSTART);
5227#endif /* CONFIG_DPP */
5228 } else {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005229 wpa_auth->dot11RSNA4WayHandshakeFailures++;
Sunil Raviaf8751c2023-03-29 11:35:17 -07005230 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
5231 LOGGER_INFO,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005232 "INITPMK - keyAvailable = false");
5233 SM_ENTER(WPA_PTK, DISCONNECT);
5234 }
5235 break;
5236 case WPA_PTK_INITPSK:
Hai Shalomfdcde762020-04-02 11:19:20 -07005237 if (wpa_auth_get_psk(wpa_auth, sm->addr, sm->p2p_dev_addr,
Hai Shalom021b0b52019-04-10 11:17:58 -07005238 NULL, NULL, NULL)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005239 SM_ENTER(WPA_PTK, PTKSTART);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005240#ifdef CONFIG_SAE
5241 } else if (wpa_auth_uses_sae(sm) && sm->pmksa) {
5242 SM_ENTER(WPA_PTK, PTKSTART);
5243#endif /* CONFIG_SAE */
Sunil Ravia04bd252022-05-02 22:54:18 -07005244 } else if (wpa_key_mgmt_wpa_psk_no_sae(sm->wpa_key_mgmt) &&
5245 wpa_auth->conf.radius_psk) {
5246 wpa_printf(MSG_DEBUG,
5247 "INITPSK: No PSK yet available for STA - use RADIUS later");
5248 SM_ENTER(WPA_PTK, PTKSTART);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005249 } else {
Sunil Raviaf8751c2023-03-29 11:35:17 -07005250 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
5251 LOGGER_INFO,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005252 "no PSK configured for the STA");
5253 wpa_auth->dot11RSNA4WayHandshakeFailures++;
5254 SM_ENTER(WPA_PTK, DISCONNECT);
5255 }
5256 break;
5257 case WPA_PTK_PTKSTART:
5258 if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest &&
5259 sm->EAPOLKeyPairwise)
5260 SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING);
Hai Shalomfdcde762020-04-02 11:19:20 -07005261 else if (sm->TimeoutCtr > conf->wpa_pairwise_update_count) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005262 wpa_auth->dot11RSNA4WayHandshakeFailures++;
Sunil Raviaf8751c2023-03-29 11:35:17 -07005263 wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
5264 LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07005265 "PTKSTART: Retry limit %u reached",
5266 conf->wpa_pairwise_update_count);
Hai Shalome21d4e82020-04-29 16:34:06 -07005267 sm->disconnect_reason =
5268 WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005269 SM_ENTER(WPA_PTK, DISCONNECT);
5270 } else if (sm->TimeoutEvt)
5271 SM_ENTER(WPA_PTK, PTKSTART);
5272 break;
5273 case WPA_PTK_PTKCALCNEGOTIATING:
5274 if (sm->MICVerified)
5275 SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING2);
5276 else if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest &&
5277 sm->EAPOLKeyPairwise)
5278 SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING);
5279 else if (sm->TimeoutEvt)
5280 SM_ENTER(WPA_PTK, PTKSTART);
5281 break;
5282 case WPA_PTK_PTKCALCNEGOTIATING2:
5283 SM_ENTER(WPA_PTK, PTKINITNEGOTIATING);
5284 break;
5285 case WPA_PTK_PTKINITNEGOTIATING:
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005286 if (sm->update_snonce)
5287 SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING);
5288 else if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest &&
5289 sm->EAPOLKeyPairwise && sm->MICVerified)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005290 SM_ENTER(WPA_PTK, PTKINITDONE);
5291 else if (sm->TimeoutCtr >
Hai Shalomfdcde762020-04-02 11:19:20 -07005292 conf->wpa_pairwise_update_count ||
5293 (conf->wpa_disable_eapol_key_retries &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005294 sm->TimeoutCtr > 1)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005295 wpa_auth->dot11RSNA4WayHandshakeFailures++;
Sunil Raviaf8751c2023-03-29 11:35:17 -07005296 wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
5297 LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07005298 "PTKINITNEGOTIATING: Retry limit %u reached",
5299 conf->wpa_pairwise_update_count);
Hai Shalome21d4e82020-04-29 16:34:06 -07005300 sm->disconnect_reason =
5301 WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005302 SM_ENTER(WPA_PTK, DISCONNECT);
5303 } else if (sm->TimeoutEvt)
5304 SM_ENTER(WPA_PTK, PTKINITNEGOTIATING);
5305 break;
5306 case WPA_PTK_PTKINITDONE:
5307 break;
5308 }
5309}
5310
5311
5312SM_STATE(WPA_PTK_GROUP, IDLE)
5313{
5314 SM_ENTRY_MA(WPA_PTK_GROUP, IDLE, wpa_ptk_group);
5315 if (sm->Init) {
5316 /* Init flag is not cleared here, so avoid busy
5317 * loop by claiming nothing changed. */
Hai Shalome21d4e82020-04-29 16:34:06 -07005318 sm->changed = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005319 }
5320 sm->GTimeoutCtr = 0;
5321}
5322
5323
5324SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING)
5325{
5326 u8 rsc[WPA_KEY_RSC_LEN];
5327 struct wpa_group *gsm = sm->group;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005328 const u8 *kde = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005329 u8 *kde_buf = NULL, *pos, hdr[2];
Sunil Ravia04bd252022-05-02 22:54:18 -07005330 size_t kde_len = 0;
Hai Shaloma20dcd72022-02-04 13:43:00 -08005331 u8 *gtk, stub_gtk[32];
Hai Shalomfdcde762020-04-02 11:19:20 -07005332 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005333 bool is_mld = false;
5334
5335#ifdef CONFIG_IEEE80211BE
5336 is_mld = sm->mld_assoc_link_id >= 0;
5337#endif /* CONFIG_IEEE80211BE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005338
5339 SM_ENTRY_MA(WPA_PTK_GROUP, REKEYNEGOTIATING, wpa_ptk_group);
5340
5341 sm->GTimeoutCtr++;
Hai Shalomfdcde762020-04-02 11:19:20 -07005342 if (conf->wpa_disable_eapol_key_retries && sm->GTimeoutCtr > 1) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005343 /* Do not allow retransmission of EAPOL-Key group msg 1/2 */
5344 return;
5345 }
Hai Shalomfdcde762020-04-02 11:19:20 -07005346 if (sm->GTimeoutCtr > conf->wpa_group_update_count) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005347 /* No point in sending the EAPOL-Key - we will disconnect
5348 * immediately following this. */
5349 return;
5350 }
5351
5352 if (sm->wpa == WPA_VERSION_WPA)
Hai Shalome21d4e82020-04-29 16:34:06 -07005353 sm->PInitAKeys = false;
5354 sm->TimeoutEvt = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005355 /* Send EAPOL(1, 1, 1, !Pair, G, RSC, GNonce, MIC(PTK), GTK[GN]) */
5356 os_memset(rsc, 0, WPA_KEY_RSC_LEN);
5357 if (gsm->wpa_group_state == WPA_GROUP_SETKEYSDONE)
5358 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc);
Sunil Raviaf8751c2023-03-29 11:35:17 -07005359 wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005360 "sending 1/2 msg of Group Key Handshake");
5361
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005362 gtk = gsm->GTK[gsm->GN - 1];
Hai Shalomfdcde762020-04-02 11:19:20 -07005363 if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005364 /*
5365 * Provide unique random GTK to each STA to prevent use
5366 * of GTK in the BSS.
5367 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08005368 if (random_get_bytes(stub_gtk, gsm->GTK_len) < 0)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005369 return;
Hai Shaloma20dcd72022-02-04 13:43:00 -08005370 gtk = stub_gtk;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005371 }
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005372
5373 if (sm->wpa == WPA_VERSION_WPA2 && !is_mld) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005374 kde_len = 2 + RSN_SELECTOR_LEN + 2 + gsm->GTK_len +
Hai Shalom74f70d42019-02-11 14:42:39 -08005375 ieee80211w_kde_len(sm) + ocv_oci_len(sm);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005376 kde_buf = os_malloc(kde_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07005377 if (!kde_buf)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005378 return;
5379
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005380 kde = pos = kde_buf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005381 hdr[0] = gsm->GN & 0x03;
5382 hdr[1] = 0;
5383 pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005384 gtk, gsm->GTK_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005385 pos = ieee80211w_kde_add(sm, pos);
Hai Shalom899fcc72020-10-19 14:38:18 -07005386 if (ocv_oci_add(sm, &pos,
5387 conf->oci_freq_override_eapol_g1) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -08005388 os_free(kde_buf);
5389 return;
5390 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005391 kde_len = pos - kde;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005392#ifdef CONFIG_IEEE80211BE
5393 } else if (sm->wpa == WPA_VERSION_WPA2 && is_mld) {
5394 kde_len = wpa_auth_ml_group_kdes_len(sm);
5395 if (kde_len) {
5396 kde_buf = os_malloc(kde_len);
5397 if (!kde_buf)
5398 return;
5399
5400 kde = pos = kde_buf;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005401 pos = wpa_auth_ml_group_kdes(sm, pos);
5402 kde_len = pos - kde_buf;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005403 }
5404#endif /* CONFIG_IEEE80211BE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005405 } else {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005406 kde = gtk;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005407 kde_len = gsm->GTK_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005408 }
5409
5410 wpa_send_eapol(sm->wpa_auth, sm,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005411 WPA_KEY_INFO_SECURE |
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005412 (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
5413 WPA_KEY_INFO_MIC : 0) |
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005414 WPA_KEY_INFO_ACK |
5415 (!sm->Pair ? WPA_KEY_INFO_INSTALL : 0),
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005416 rsc, NULL, kde, kde_len, gsm->GN, 1);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005417
Sunil Ravia04bd252022-05-02 22:54:18 -07005418 bin_clear_free(kde_buf, kde_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005419}
5420
5421
5422SM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED)
5423{
Hai Shalom74f70d42019-02-11 14:42:39 -08005424 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
Hai Shalomfdcde762020-04-02 11:19:20 -07005425#ifdef CONFIG_OCV
Hai Shalom74f70d42019-02-11 14:42:39 -08005426 const u8 *key_data, *mic;
5427 struct ieee802_1x_hdr *hdr;
5428 struct wpa_eapol_key *key;
5429 struct wpa_eapol_ie_parse kde;
5430 size_t mic_len;
5431 u16 key_data_length;
5432#endif /* CONFIG_OCV */
5433
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005434 SM_ENTRY_MA(WPA_PTK_GROUP, REKEYESTABLISHED, wpa_ptk_group);
Hai Shalome21d4e82020-04-29 16:34:06 -07005435 sm->EAPOLKeyReceived = false;
Hai Shalom74f70d42019-02-11 14:42:39 -08005436
5437#ifdef CONFIG_OCV
5438 mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
5439
5440 /*
5441 * Note: last_rx_eapol_key length fields have already been validated in
5442 * wpa_receive().
5443 */
5444 hdr = (struct ieee802_1x_hdr *) sm->last_rx_eapol_key;
5445 key = (struct wpa_eapol_key *) (hdr + 1);
5446 mic = (u8 *) (key + 1);
5447 key_data = mic + mic_len + 2;
5448 key_data_length = WPA_GET_BE16(mic + mic_len);
5449 if (key_data_length > sm->last_rx_eapol_key_len - sizeof(*hdr) -
5450 sizeof(*key) - mic_len - 2)
5451 return;
5452
5453 if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07005454 wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
Hai Shalom74f70d42019-02-11 14:42:39 -08005455 "received EAPOL-Key group msg 2/2 with invalid Key Data contents");
5456 return;
5457 }
5458
5459 if (wpa_auth_uses_ocv(sm)) {
5460 struct wpa_channel_info ci;
5461 int tx_chanwidth;
5462 int tx_seg1_idx;
5463
5464 if (wpa_channel_info(wpa_auth, &ci) != 0) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07005465 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
5466 LOGGER_INFO,
Hai Shalom899fcc72020-10-19 14:38:18 -07005467 "Failed to get channel info to validate received OCI in EAPOL-Key group 2/2");
Hai Shalom74f70d42019-02-11 14:42:39 -08005468 return;
5469 }
5470
5471 if (get_sta_tx_parameters(sm,
5472 channel_width_to_int(ci.chanwidth),
5473 ci.seg1_idx, &tx_chanwidth,
5474 &tx_seg1_idx) < 0)
5475 return;
5476
5477 if (ocv_verify_tx_params(kde.oci, kde.oci_len, &ci,
Hai Shalom899fcc72020-10-19 14:38:18 -07005478 tx_chanwidth, tx_seg1_idx) !=
5479 OCI_SUCCESS) {
Sunil Raviaf8751c2023-03-29 11:35:17 -07005480 wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
5481 LOGGER_INFO,
Hai Shalom899fcc72020-10-19 14:38:18 -07005482 "OCV failed: %s", ocv_errorstr);
5483 if (wpa_auth->conf.msg_ctx)
5484 wpa_msg(wpa_auth->conf.msg_ctx, MSG_INFO,
5485 OCV_FAILURE "addr=" MACSTR
5486 " frame=eapol-key-g2 error=%s",
Sunil Raviaf8751c2023-03-29 11:35:17 -07005487 MAC2STR(wpa_auth_get_spa(sm)),
5488 ocv_errorstr);
Hai Shalom74f70d42019-02-11 14:42:39 -08005489 return;
5490 }
5491 }
5492#endif /* CONFIG_OCV */
5493
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005494 if (sm->GUpdateStationKeys)
Sunil Ravi7f769292024-07-23 22:21:32 +00005495 wpa_gkeydone_sta(sm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005496 sm->GTimeoutCtr = 0;
5497 /* FIX: MLME.SetProtection.Request(TA, Tx_Rx) */
Sunil Raviaf8751c2023-03-29 11:35:17 -07005498 wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005499 "group key handshake completed (%s)",
5500 sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN");
Hai Shalome21d4e82020-04-29 16:34:06 -07005501 sm->has_GTK = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005502}
5503
5504
5505SM_STATE(WPA_PTK_GROUP, KEYERROR)
5506{
5507 SM_ENTRY_MA(WPA_PTK_GROUP, KEYERROR, wpa_ptk_group);
5508 if (sm->GUpdateStationKeys)
Sunil Ravi7f769292024-07-23 22:21:32 +00005509 wpa_gkeydone_sta(sm);
5510 if (sm->wpa_auth->conf.no_disconnect_on_group_keyerror &&
5511 sm->wpa == WPA_VERSION_WPA2) {
5512 wpa_auth_vlogger(sm->wpa_auth, wpa_auth_get_spa(sm),
5513 LOGGER_DEBUG,
5514 "group key handshake failed after %u tries - allow STA to remain connected",
5515 sm->wpa_auth->conf.wpa_group_update_count);
5516 return;
5517 }
Hai Shalome21d4e82020-04-29 16:34:06 -07005518 sm->Disconnect = true;
5519 sm->disconnect_reason = WLAN_REASON_GROUP_KEY_UPDATE_TIMEOUT;
Sunil Raviaf8751c2023-03-29 11:35:17 -07005520 wpa_auth_vlogger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005521 "group key handshake failed (%s) after %u tries",
5522 sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN",
5523 sm->wpa_auth->conf.wpa_group_update_count);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005524}
5525
5526
5527SM_STEP(WPA_PTK_GROUP)
5528{
5529 if (sm->Init || sm->PtkGroupInit) {
5530 SM_ENTER(WPA_PTK_GROUP, IDLE);
Hai Shalome21d4e82020-04-29 16:34:06 -07005531 sm->PtkGroupInit = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005532 } else switch (sm->wpa_ptk_group_state) {
5533 case WPA_PTK_GROUP_IDLE:
5534 if (sm->GUpdateStationKeys ||
5535 (sm->wpa == WPA_VERSION_WPA && sm->PInitAKeys))
5536 SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING);
5537 break;
5538 case WPA_PTK_GROUP_REKEYNEGOTIATING:
5539 if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest &&
5540 !sm->EAPOLKeyPairwise && sm->MICVerified)
5541 SM_ENTER(WPA_PTK_GROUP, REKEYESTABLISHED);
5542 else if (sm->GTimeoutCtr >
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005543 sm->wpa_auth->conf.wpa_group_update_count ||
5544 (sm->wpa_auth->conf.wpa_disable_eapol_key_retries &&
5545 sm->GTimeoutCtr > 1))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005546 SM_ENTER(WPA_PTK_GROUP, KEYERROR);
5547 else if (sm->TimeoutEvt)
5548 SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING);
5549 break;
5550 case WPA_PTK_GROUP_KEYERROR:
5551 SM_ENTER(WPA_PTK_GROUP, IDLE);
5552 break;
5553 case WPA_PTK_GROUP_REKEYESTABLISHED:
5554 SM_ENTER(WPA_PTK_GROUP, IDLE);
5555 break;
5556 }
5557}
5558
5559
5560static int wpa_gtk_update(struct wpa_authenticator *wpa_auth,
5561 struct wpa_group *group)
5562{
Hai Shalomfdcde762020-04-02 11:19:20 -07005563 struct wpa_auth_config *conf = &wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005564 int ret = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07005565 size_t len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005566
5567 os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
5568 inc_byte_array(group->Counter, WPA_NONCE_LEN);
5569 if (wpa_gmk_to_gtk(group->GMK, "Group key expansion",
5570 wpa_auth->addr, group->GNonce,
5571 group->GTK[group->GN - 1], group->GTK_len) < 0)
5572 ret = -1;
5573 wpa_hexdump_key(MSG_DEBUG, "GTK",
5574 group->GTK[group->GN - 1], group->GTK_len);
5575
Hai Shalomfdcde762020-04-02 11:19:20 -07005576 if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
5577 len = wpa_cipher_key_len(conf->group_mgmt_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005578 os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
5579 inc_byte_array(group->Counter, WPA_NONCE_LEN);
5580 if (wpa_gmk_to_gtk(group->GMK, "IGTK key expansion",
5581 wpa_auth->addr, group->GNonce,
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07005582 group->IGTK[group->GN_igtk - 4], len) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005583 ret = -1;
5584 wpa_hexdump_key(MSG_DEBUG, "IGTK",
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07005585 group->IGTK[group->GN_igtk - 4], len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005586 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005587
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005588 if (!wpa_auth->non_tx_beacon_prot &&
5589 conf->ieee80211w == NO_MGMT_FRAME_PROTECTION)
5590 return ret;
5591 if (!conf->beacon_prot)
5592 return ret;
5593
5594 if (wpa_auth->conf.tx_bss_auth) {
5595 group = wpa_auth->conf.tx_bss_auth->group;
5596 if (group->bigtk_set)
5597 return ret;
5598 wpa_printf(MSG_DEBUG, "Set up BIGTK for TX BSS");
Hai Shalomfdcde762020-04-02 11:19:20 -07005599 }
5600
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005601 len = wpa_cipher_key_len(conf->group_mgmt_cipher);
5602 os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
5603 inc_byte_array(group->Counter, WPA_NONCE_LEN);
5604 if (wpa_gmk_to_gtk(group->GMK, "BIGTK key expansion",
5605 wpa_auth->addr, group->GNonce,
5606 group->BIGTK[group->GN_bigtk - 6], len) < 0)
5607 return -1;
5608 group->bigtk_set = true;
5609 wpa_hexdump_key(MSG_DEBUG, "BIGTK",
5610 group->BIGTK[group->GN_bigtk - 6], len);
5611
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005612 return ret;
5613}
5614
5615
5616static void wpa_group_gtk_init(struct wpa_authenticator *wpa_auth,
5617 struct wpa_group *group)
5618{
Hai Shalomfdcde762020-04-02 11:19:20 -07005619 wpa_printf(MSG_DEBUG,
5620 "WPA: group state machine entering state GTK_INIT (VLAN-ID %d)",
5621 group->vlan_id);
Hai Shalome21d4e82020-04-29 16:34:06 -07005622 group->changed = false; /* GInit is not cleared here; avoid loop */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005623 group->wpa_group_state = WPA_GROUP_GTK_INIT;
5624
5625 /* GTK[0..N] = 0 */
5626 os_memset(group->GTK, 0, sizeof(group->GTK));
5627 group->GN = 1;
5628 group->GM = 2;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005629 group->GN_igtk = 4;
5630 group->GM_igtk = 5;
Hai Shalomfdcde762020-04-02 11:19:20 -07005631 group->GN_bigtk = 6;
5632 group->GM_bigtk = 7;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005633 /* GTK[GN] = CalcGTK() */
5634 wpa_gtk_update(wpa_auth, group);
5635}
5636
5637
5638static int wpa_group_update_sta(struct wpa_state_machine *sm, void *ctx)
5639{
Sunil Ravic0f5d412024-09-11 22:12:49 +00005640 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
5641 struct wpa_group *group = sm->group;
5642#ifdef CONFIG_IEEE80211BE
5643 int link_id;
5644
5645 for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
5646 if (!sm->mld_links[link_id].valid)
5647 continue;
5648 if (sm->mld_links[link_id].wpa_auth &&
5649 sm->mld_links[link_id].wpa_auth->group == ctx) {
5650 group = sm->mld_links[link_id].wpa_auth->group;
5651 wpa_auth = sm->mld_links[link_id].wpa_auth;
5652 break;
5653 }
5654 }
5655#endif /* CONFIG_IEEE80211BE */
5656
5657 if (ctx && ctx != group)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005658 return 0;
5659
Sunil Ravic0f5d412024-09-11 22:12:49 +00005660#ifdef CONFIG_IEEE80211BE
5661 /* For ML STA, run rekey on the association link and send G1 with keys
5662 * for all links. This is based on assumption that MLD level
5663 * Authenticator updates group keys on all affiliated links in one shot
5664 * and not independently or concurrently for separate links. */
5665 if (sm->mld_assoc_link_id >= 0 &&
5666 sm->mld_assoc_link_id != wpa_auth->link_id)
5667 return 0;
5668#endif /* CONFIG_IEEE80211BE */
5669
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005670 if (sm->wpa_ptk_state != WPA_PTK_PTKINITDONE) {
Sunil Ravic0f5d412024-09-11 22:12:49 +00005671 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
Sunil Raviaf8751c2023-03-29 11:35:17 -07005672 LOGGER_DEBUG,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005673 "Not in PTKINITDONE; skip Group Key update");
Hai Shalome21d4e82020-04-29 16:34:06 -07005674 sm->GUpdateStationKeys = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005675 return 0;
5676 }
5677 if (sm->GUpdateStationKeys) {
5678 /*
5679 * This should not really happen, so add a debug log entry.
5680 * Since we clear the GKeyDoneStations before the loop, the
5681 * station needs to be counted here anyway.
5682 */
Sunil Ravic0f5d412024-09-11 22:12:49 +00005683 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
Sunil Raviaf8751c2023-03-29 11:35:17 -07005684 LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07005685 "GUpdateStationKeys was already set when marking station for GTK rekeying");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005686 }
5687
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005688 /* Do not rekey GTK/IGTK when STA is in WNM-Sleep Mode */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005689 if (sm->is_wnmsleep)
5690 return 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005691
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005692 sm->group->GKeyDoneStations++;
Sunil Ravic0f5d412024-09-11 22:12:49 +00005693#ifdef CONFIG_IEEE80211BE
5694 for_each_sm_auth(sm, link_id)
5695 sm->mld_links[link_id].wpa_auth->group->GKeyDoneStations++;
5696#endif /* CONFIG_IEEE80211BE */
5697
Hai Shalome21d4e82020-04-29 16:34:06 -07005698 sm->GUpdateStationKeys = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005699
5700 wpa_sm_step(sm);
5701 return 0;
5702}
5703
5704
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005705#ifdef CONFIG_WNM_AP
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005706/* update GTK when exiting WNM-Sleep Mode */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005707void wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm)
5708{
Hai Shalomfdcde762020-04-02 11:19:20 -07005709 if (!sm || sm->is_wnmsleep)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005710 return;
5711
5712 wpa_group_update_sta(sm, NULL);
5713}
5714
5715
5716void wpa_set_wnmsleep(struct wpa_state_machine *sm, int flag)
5717{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005718 if (sm)
5719 sm->is_wnmsleep = !!flag;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005720}
5721
5722
5723int wpa_wnmsleep_gtk_subelem(struct wpa_state_machine *sm, u8 *pos)
5724{
Hai Shalom899fcc72020-10-19 14:38:18 -07005725 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005726 struct wpa_group *gsm = sm->group;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005727 u8 *start = pos;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005728
5729 /*
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005730 * GTK subelement:
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005731 * Sub-elem ID[1] | Length[1] | Key Info[2] | Key Length[1] | RSC[8] |
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005732 * Key[5..32]
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005733 */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005734 *pos++ = WNM_SLEEP_SUBELEM_GTK;
5735 *pos++ = 11 + gsm->GTK_len;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005736 /* Key ID in B0-B1 of Key Info */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005737 WPA_PUT_LE16(pos, gsm->GN & 0x03);
5738 pos += 2;
5739 *pos++ = gsm->GTK_len;
5740 if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, pos) != 0)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005741 return 0;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005742 pos += 8;
5743 os_memcpy(pos, gsm->GTK[gsm->GN - 1], gsm->GTK_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07005744 if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
5745 /*
5746 * Provide unique random GTK to each STA to prevent use
5747 * of GTK in the BSS.
5748 */
5749 if (random_get_bytes(pos, gsm->GTK_len) < 0)
5750 return 0;
5751 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005752 pos += gsm->GTK_len;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005753
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005754 wpa_printf(MSG_DEBUG, "WNM: GTK Key ID %u in WNM-Sleep Mode exit",
5755 gsm->GN);
5756 wpa_hexdump_key(MSG_DEBUG, "WNM: GTK in WNM-Sleep Mode exit",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005757 gsm->GTK[gsm->GN - 1], gsm->GTK_len);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005758
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005759 return pos - start;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005760}
5761
5762
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005763int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos)
5764{
Hai Shalom899fcc72020-10-19 14:38:18 -07005765 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005766 struct wpa_group *gsm = sm->group;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005767 u8 *start = pos;
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07005768 size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005769
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005770 /*
5771 * IGTK subelement:
5772 * Sub-elem ID[1] | Length[1] | KeyID[2] | PN[6] | Key[16]
5773 */
5774 *pos++ = WNM_SLEEP_SUBELEM_IGTK;
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07005775 *pos++ = 2 + 6 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005776 WPA_PUT_LE16(pos, gsm->GN_igtk);
5777 pos += 2;
5778 if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, pos) != 0)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005779 return 0;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005780 pos += 6;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005781
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07005782 os_memcpy(pos, gsm->IGTK[gsm->GN_igtk - 4], len);
Hai Shalom899fcc72020-10-19 14:38:18 -07005783 if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
5784 /*
5785 * Provide unique random IGTK to each STA to prevent use
5786 * of IGTK in the BSS.
5787 */
5788 if (random_get_bytes(pos, len) < 0)
5789 return 0;
5790 }
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07005791 pos += len;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005792
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005793 wpa_printf(MSG_DEBUG, "WNM: IGTK Key ID %u in WNM-Sleep Mode exit",
5794 gsm->GN_igtk);
5795 wpa_hexdump_key(MSG_DEBUG, "WNM: IGTK in WNM-Sleep Mode exit",
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07005796 gsm->IGTK[gsm->GN_igtk - 4], len);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005797
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005798 return pos - start;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005799}
Hai Shalomc3565922019-10-28 11:58:20 -07005800
Hai Shalomfdcde762020-04-02 11:19:20 -07005801
5802int wpa_wnmsleep_bigtk_subelem(struct wpa_state_machine *sm, u8 *pos)
5803{
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005804 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
5805 struct wpa_group *gsm = wpa_auth->group;
Hai Shalomfdcde762020-04-02 11:19:20 -07005806 u8 *start = pos;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005807 size_t len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher);
Hai Shalomfdcde762020-04-02 11:19:20 -07005808
5809 /*
5810 * BIGTK subelement:
5811 * Sub-elem ID[1] | Length[1] | KeyID[2] | PN[6] | Key[16]
5812 */
5813 *pos++ = WNM_SLEEP_SUBELEM_BIGTK;
5814 *pos++ = 2 + 6 + len;
5815 WPA_PUT_LE16(pos, gsm->GN_bigtk);
5816 pos += 2;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005817 if (wpa_auth_get_seqnum(wpa_auth, NULL, gsm->GN_bigtk, pos) != 0)
Hai Shalomfdcde762020-04-02 11:19:20 -07005818 return 0;
5819 pos += 6;
5820
5821 os_memcpy(pos, gsm->BIGTK[gsm->GN_bigtk - 6], len);
Hai Shalom899fcc72020-10-19 14:38:18 -07005822 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
5823 /*
5824 * Provide unique random BIGTK to each STA to prevent use
5825 * of BIGTK in the BSS.
5826 */
5827 if (random_get_bytes(pos, len) < 0)
5828 return 0;
5829 }
Hai Shalomfdcde762020-04-02 11:19:20 -07005830 pos += len;
5831
5832 wpa_printf(MSG_DEBUG, "WNM: BIGTK Key ID %u in WNM-Sleep Mode exit",
5833 gsm->GN_bigtk);
5834 wpa_hexdump_key(MSG_DEBUG, "WNM: BIGTK in WNM-Sleep Mode exit",
Hai Shaloma20dcd72022-02-04 13:43:00 -08005835 gsm->BIGTK[gsm->GN_bigtk - 6], len);
Hai Shalomfdcde762020-04-02 11:19:20 -07005836
5837 return pos - start;
5838}
5839
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005840#endif /* CONFIG_WNM_AP */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005841
5842
Sunil Ravi7f769292024-07-23 22:21:32 +00005843static void wpa_group_update_gtk(struct wpa_authenticator *wpa_auth,
5844 struct wpa_group *group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005845{
5846 int tmp;
5847
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005848 tmp = group->GM;
5849 group->GM = group->GN;
5850 group->GN = tmp;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005851 tmp = group->GM_igtk;
5852 group->GM_igtk = group->GN_igtk;
5853 group->GN_igtk = tmp;
Hai Shalomfdcde762020-04-02 11:19:20 -07005854 tmp = group->GM_bigtk;
5855 group->GM_bigtk = group->GN_bigtk;
5856 group->GN_bigtk = tmp;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005857 /* "GKeyDoneStations = GNoStations" is done in more robust way by
5858 * counting the STAs that are marked with GUpdateStationKeys instead of
5859 * including all STAs that could be in not-yet-completed state. */
5860 wpa_gtk_update(wpa_auth, group);
Sunil Ravi7f769292024-07-23 22:21:32 +00005861}
5862
5863
5864static void wpa_group_setkeys(struct wpa_authenticator *wpa_auth,
5865 struct wpa_group *group)
5866{
5867 wpa_printf(MSG_DEBUG,
5868 "WPA: group state machine entering state SETKEYS (VLAN-ID %d)",
5869 group->vlan_id);
5870 group->changed = true;
5871 group->wpa_group_state = WPA_GROUP_SETKEYS;
5872 group->GTKReKey = false;
5873
5874#ifdef CONFIG_IEEE80211BE
5875 if (wpa_auth->is_ml)
5876 goto skip_update;
5877#endif /* CONFIG_IEEE80211BE */
5878
5879 wpa_group_update_gtk(wpa_auth, group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005880
5881 if (group->GKeyDoneStations) {
Hai Shalomfdcde762020-04-02 11:19:20 -07005882 wpa_printf(MSG_DEBUG,
5883 "wpa_group_setkeys: Unexpected GKeyDoneStations=%d when starting new GTK rekey",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005884 group->GKeyDoneStations);
5885 group->GKeyDoneStations = 0;
5886 }
Sunil Ravi7f769292024-07-23 22:21:32 +00005887
5888#ifdef CONFIG_IEEE80211BE
5889skip_update:
5890#endif /* CONFIG_IEEE80211BE */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005891 wpa_auth_for_each_sta(wpa_auth, wpa_group_update_sta, group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005892 wpa_printf(MSG_DEBUG, "wpa_group_setkeys: GKeyDoneStations=%d",
5893 group->GKeyDoneStations);
5894}
5895
5896
5897static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth,
5898 struct wpa_group *group)
5899{
Hai Shalomfdcde762020-04-02 11:19:20 -07005900 struct wpa_auth_config *conf = &wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005901 int ret = 0;
5902
5903 if (wpa_auth_set_key(wpa_auth, group->vlan_id,
Hai Shalomfdcde762020-04-02 11:19:20 -07005904 wpa_cipher_to_alg(conf->wpa_group),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005905 broadcast_ether_addr, group->GN,
Hai Shalomfdcde762020-04-02 11:19:20 -07005906 group->GTK[group->GN - 1], group->GTK_len,
5907 KEY_FLAG_GROUP_TX_DEFAULT) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005908 ret = -1;
5909
Hai Shalomfdcde762020-04-02 11:19:20 -07005910 if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07005911 enum wpa_alg alg;
5912 size_t len;
5913
Hai Shalomfdcde762020-04-02 11:19:20 -07005914 alg = wpa_cipher_to_alg(conf->group_mgmt_cipher);
5915 len = wpa_cipher_key_len(conf->group_mgmt_cipher);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07005916
5917 if (ret == 0 &&
5918 wpa_auth_set_key(wpa_auth, group->vlan_id, alg,
5919 broadcast_ether_addr, group->GN_igtk,
Hai Shalomfdcde762020-04-02 11:19:20 -07005920 group->IGTK[group->GN_igtk - 4], len,
5921 KEY_FLAG_GROUP_TX_DEFAULT) < 0)
5922 ret = -1;
5923
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005924 if (ret || !conf->beacon_prot)
5925 return ret;
5926 if (wpa_auth->conf.tx_bss_auth) {
5927 wpa_auth = wpa_auth->conf.tx_bss_auth;
5928 group = wpa_auth->group;
5929 if (!group->bigtk_set || group->bigtk_configured)
5930 return ret;
5931 }
5932 if (wpa_auth_set_key(wpa_auth, group->vlan_id, alg,
Hai Shalomfdcde762020-04-02 11:19:20 -07005933 broadcast_ether_addr, group->GN_bigtk,
5934 group->BIGTK[group->GN_bigtk - 6], len,
5935 KEY_FLAG_GROUP_TX_DEFAULT) < 0)
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07005936 ret = -1;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005937 else
5938 group->bigtk_configured = true;
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07005939 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005940
5941 return ret;
5942}
5943
5944
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005945static int wpa_group_disconnect_cb(struct wpa_state_machine *sm, void *ctx)
5946{
5947 if (sm->group == ctx) {
5948 wpa_printf(MSG_DEBUG, "WPA: Mark STA " MACSTR
Hai Shalomfdcde762020-04-02 11:19:20 -07005949 " for disconnection due to fatal failure",
Sunil Raviaf8751c2023-03-29 11:35:17 -07005950 MAC2STR(wpa_auth_get_spa(sm)));
Hai Shalome21d4e82020-04-29 16:34:06 -07005951 sm->Disconnect = true;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005952 }
5953
5954 return 0;
5955}
5956
5957
5958static void wpa_group_fatal_failure(struct wpa_authenticator *wpa_auth,
5959 struct wpa_group *group)
5960{
Hai Shalomfdcde762020-04-02 11:19:20 -07005961 wpa_printf(MSG_DEBUG,
5962 "WPA: group state machine entering state FATAL_FAILURE");
Hai Shalome21d4e82020-04-29 16:34:06 -07005963 group->changed = true;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005964 group->wpa_group_state = WPA_GROUP_FATAL_FAILURE;
5965 wpa_auth_for_each_sta(wpa_auth, wpa_group_disconnect_cb, group);
5966}
5967
5968
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005969static int wpa_group_setkeysdone(struct wpa_authenticator *wpa_auth,
5970 struct wpa_group *group)
5971{
Hai Shalomfdcde762020-04-02 11:19:20 -07005972 wpa_printf(MSG_DEBUG,
5973 "WPA: group state machine entering state SETKEYSDONE (VLAN-ID %d)",
5974 group->vlan_id);
Hai Shalome21d4e82020-04-29 16:34:06 -07005975 group->changed = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005976 group->wpa_group_state = WPA_GROUP_SETKEYSDONE;
5977
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005978 if (wpa_group_config_group_keys(wpa_auth, group) < 0) {
5979 wpa_group_fatal_failure(wpa_auth, group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005980 return -1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005981 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005982
5983 return 0;
5984}
5985
5986
5987static void wpa_group_sm_step(struct wpa_authenticator *wpa_auth,
5988 struct wpa_group *group)
5989{
5990 if (group->GInit) {
5991 wpa_group_gtk_init(wpa_auth, group);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005992 } else if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) {
5993 /* Do not allow group operations */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005994 } else if (group->wpa_group_state == WPA_GROUP_GTK_INIT &&
5995 group->GTKAuthenticator) {
5996 wpa_group_setkeysdone(wpa_auth, group);
5997 } else if (group->wpa_group_state == WPA_GROUP_SETKEYSDONE &&
5998 group->GTKReKey) {
5999 wpa_group_setkeys(wpa_auth, group);
6000 } else if (group->wpa_group_state == WPA_GROUP_SETKEYS) {
6001 if (group->GKeyDoneStations == 0)
6002 wpa_group_setkeysdone(wpa_auth, group);
6003 else if (group->GTKReKey)
6004 wpa_group_setkeys(wpa_auth, group);
6005 }
6006}
6007
6008
Sunil Ravi7f769292024-07-23 22:21:32 +00006009static void wpa_clear_changed(struct wpa_state_machine *sm)
6010{
6011#ifdef CONFIG_IEEE80211BE
6012 int link_id;
6013#endif /* CONFIG_IEEE80211BE */
6014
6015 sm->changed = false;
6016 sm->wpa_auth->group->changed = false;
6017
6018#ifdef CONFIG_IEEE80211BE
6019 for_each_sm_auth(sm, link_id)
6020 sm->mld_links[link_id].wpa_auth->group->changed = false;
6021#endif /* CONFIG_IEEE80211BE */
6022}
6023
6024
6025static void wpa_group_sm_step_links(struct wpa_state_machine *sm)
6026{
6027#ifdef CONFIG_IEEE80211BE
6028 int link_id;
6029#endif /* CONFIG_IEEE80211BE */
6030
6031 if (!sm || !sm->wpa_auth)
6032 return;
6033 wpa_group_sm_step(sm->wpa_auth, sm->wpa_auth->group);
6034
6035#ifdef CONFIG_IEEE80211BE
6036 for_each_sm_auth(sm, link_id) {
6037 wpa_group_sm_step(sm->mld_links[link_id].wpa_auth,
6038 sm->mld_links[link_id].wpa_auth->group);
6039 }
6040#endif /* CONFIG_IEEE80211BE */
6041}
6042
6043
6044static bool wpa_group_sm_changed(struct wpa_state_machine *sm)
6045{
6046#ifdef CONFIG_IEEE80211BE
6047 int link_id;
6048#endif /* CONFIG_IEEE80211BE */
6049 bool changed;
6050
6051 if (!sm || !sm->wpa_auth)
6052 return false;
6053 changed = sm->wpa_auth->group->changed;
6054
6055#ifdef CONFIG_IEEE80211BE
6056 for_each_sm_auth(sm, link_id)
6057 changed |= sm->mld_links[link_id].wpa_auth->group->changed;
6058#endif /* CONFIG_IEEE80211BE */
6059
6060 return changed;
6061}
6062
6063
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006064static int wpa_sm_step(struct wpa_state_machine *sm)
6065{
Hai Shalomfdcde762020-04-02 11:19:20 -07006066 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006067 return 0;
6068
6069 if (sm->in_step_loop) {
6070 /* This should not happen, but if it does, make sure we do not
6071 * end up freeing the state machine too early by exiting the
6072 * recursive call. */
6073 wpa_printf(MSG_ERROR, "WPA: wpa_sm_step() called recursively");
6074 return 0;
6075 }
6076
6077 sm->in_step_loop = 1;
6078 do {
6079 if (sm->pending_deinit)
6080 break;
6081
Sunil Ravi7f769292024-07-23 22:21:32 +00006082 wpa_clear_changed(sm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006083
6084 SM_STEP_RUN(WPA_PTK);
6085 if (sm->pending_deinit)
6086 break;
6087 SM_STEP_RUN(WPA_PTK_GROUP);
6088 if (sm->pending_deinit)
6089 break;
Sunil Ravi7f769292024-07-23 22:21:32 +00006090 wpa_group_sm_step_links(sm);
6091 } while (sm->changed || wpa_group_sm_changed(sm));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006092 sm->in_step_loop = 0;
6093
6094 if (sm->pending_deinit) {
Hai Shalomfdcde762020-04-02 11:19:20 -07006095 wpa_printf(MSG_DEBUG,
6096 "WPA: Completing pending STA state machine deinit for "
Sunil Raviaf8751c2023-03-29 11:35:17 -07006097 MACSTR, MAC2STR(wpa_auth_get_spa(sm)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006098 wpa_free_sta_sm(sm);
6099 return 1;
6100 }
6101 return 0;
6102}
6103
6104
6105static void wpa_sm_call_step(void *eloop_ctx, void *timeout_ctx)
6106{
6107 struct wpa_state_machine *sm = eloop_ctx;
6108 wpa_sm_step(sm);
6109}
6110
6111
6112void wpa_auth_sm_notify(struct wpa_state_machine *sm)
6113{
Hai Shalomfdcde762020-04-02 11:19:20 -07006114 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006115 return;
6116 eloop_register_timeout(0, 0, wpa_sm_call_step, sm, NULL);
6117}
6118
6119
6120void wpa_gtk_rekey(struct wpa_authenticator *wpa_auth)
6121{
6122 int tmp, i;
6123 struct wpa_group *group;
6124
Hai Shalomfdcde762020-04-02 11:19:20 -07006125 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006126 return;
6127
6128 group = wpa_auth->group;
6129
6130 for (i = 0; i < 2; i++) {
6131 tmp = group->GM;
6132 group->GM = group->GN;
6133 group->GN = tmp;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006134 tmp = group->GM_igtk;
6135 group->GM_igtk = group->GN_igtk;
6136 group->GN_igtk = tmp;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00006137 if (!wpa_auth->conf.tx_bss_auth) {
6138 tmp = group->GM_bigtk;
6139 group->GM_bigtk = group->GN_bigtk;
6140 group->GN_bigtk = tmp;
6141 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006142 wpa_gtk_update(wpa_auth, group);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006143 wpa_group_config_group_keys(wpa_auth, group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006144 }
6145}
6146
6147
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07006148static const char * wpa_bool_txt(int val)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006149{
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07006150 return val ? "TRUE" : "FALSE";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006151}
6152
6153
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006154#define RSN_SUITE "%02x-%02x-%02x-%d"
6155#define RSN_SUITE_ARG(s) \
6156((s) >> 24) & 0xff, ((s) >> 16) & 0xff, ((s) >> 8) & 0xff, (s) & 0xff
6157
6158int wpa_get_mib(struct wpa_authenticator *wpa_auth, char *buf, size_t buflen)
6159{
Hai Shalomfdcde762020-04-02 11:19:20 -07006160 struct wpa_auth_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006161 int len = 0, ret;
6162 char pmkid_txt[PMKID_LEN * 2 + 1];
6163#ifdef CONFIG_RSN_PREAUTH
6164 const int preauth = 1;
6165#else /* CONFIG_RSN_PREAUTH */
6166 const int preauth = 0;
6167#endif /* CONFIG_RSN_PREAUTH */
6168
Hai Shalomfdcde762020-04-02 11:19:20 -07006169 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006170 return len;
Hai Shalomfdcde762020-04-02 11:19:20 -07006171 conf = &wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006172
6173 ret = os_snprintf(buf + len, buflen - len,
6174 "dot11RSNAOptionImplemented=TRUE\n"
6175 "dot11RSNAPreauthenticationImplemented=%s\n"
6176 "dot11RSNAEnabled=%s\n"
6177 "dot11RSNAPreauthenticationEnabled=%s\n",
6178 wpa_bool_txt(preauth),
Hai Shalomfdcde762020-04-02 11:19:20 -07006179 wpa_bool_txt(conf->wpa & WPA_PROTO_RSN),
6180 wpa_bool_txt(conf->rsn_preauth));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006181 if (os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006182 return len;
6183 len += ret;
6184
6185 wpa_snprintf_hex(pmkid_txt, sizeof(pmkid_txt),
6186 wpa_auth->dot11RSNAPMKIDUsed, PMKID_LEN);
6187
6188 ret = os_snprintf(
6189 buf + len, buflen - len,
6190 "dot11RSNAConfigVersion=%u\n"
6191 "dot11RSNAConfigPairwiseKeysSupported=9999\n"
6192 /* FIX: dot11RSNAConfigGroupCipher */
6193 /* FIX: dot11RSNAConfigGroupRekeyMethod */
6194 /* FIX: dot11RSNAConfigGroupRekeyTime */
6195 /* FIX: dot11RSNAConfigGroupRekeyPackets */
6196 "dot11RSNAConfigGroupRekeyStrict=%u\n"
6197 "dot11RSNAConfigGroupUpdateCount=%u\n"
6198 "dot11RSNAConfigPairwiseUpdateCount=%u\n"
6199 "dot11RSNAConfigGroupCipherSize=%u\n"
6200 "dot11RSNAConfigPMKLifetime=%u\n"
6201 "dot11RSNAConfigPMKReauthThreshold=%u\n"
6202 "dot11RSNAConfigNumberOfPTKSAReplayCounters=0\n"
6203 "dot11RSNAConfigSATimeout=%u\n"
6204 "dot11RSNAAuthenticationSuiteSelected=" RSN_SUITE "\n"
6205 "dot11RSNAPairwiseCipherSelected=" RSN_SUITE "\n"
6206 "dot11RSNAGroupCipherSelected=" RSN_SUITE "\n"
6207 "dot11RSNAPMKIDUsed=%s\n"
6208 "dot11RSNAAuthenticationSuiteRequested=" RSN_SUITE "\n"
6209 "dot11RSNAPairwiseCipherRequested=" RSN_SUITE "\n"
6210 "dot11RSNAGroupCipherRequested=" RSN_SUITE "\n"
6211 "dot11RSNATKIPCounterMeasuresInvoked=%u\n"
6212 "dot11RSNA4WayHandshakeFailures=%u\n"
6213 "dot11RSNAConfigNumberOfGTKSAReplayCounters=0\n",
6214 RSN_VERSION,
Hai Shalomfdcde762020-04-02 11:19:20 -07006215 !!conf->wpa_strict_rekey,
6216 conf->wpa_group_update_count,
6217 conf->wpa_pairwise_update_count,
6218 wpa_cipher_key_len(conf->wpa_group) * 8,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006219 dot11RSNAConfigPMKLifetime,
6220 dot11RSNAConfigPMKReauthThreshold,
6221 dot11RSNAConfigSATimeout,
6222 RSN_SUITE_ARG(wpa_auth->dot11RSNAAuthenticationSuiteSelected),
6223 RSN_SUITE_ARG(wpa_auth->dot11RSNAPairwiseCipherSelected),
6224 RSN_SUITE_ARG(wpa_auth->dot11RSNAGroupCipherSelected),
6225 pmkid_txt,
6226 RSN_SUITE_ARG(wpa_auth->dot11RSNAAuthenticationSuiteRequested),
6227 RSN_SUITE_ARG(wpa_auth->dot11RSNAPairwiseCipherRequested),
6228 RSN_SUITE_ARG(wpa_auth->dot11RSNAGroupCipherRequested),
6229 wpa_auth->dot11RSNATKIPCounterMeasuresInvoked,
6230 wpa_auth->dot11RSNA4WayHandshakeFailures);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006231 if (os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006232 return len;
6233 len += ret;
6234
6235 /* TODO: dot11RSNAConfigPairwiseCiphersTable */
6236 /* TODO: dot11RSNAConfigAuthenticationSuitesTable */
6237
6238 /* Private MIB */
6239 ret = os_snprintf(buf + len, buflen - len, "hostapdWPAGroupState=%d\n",
6240 wpa_auth->group->wpa_group_state);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006241 if (os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006242 return len;
6243 len += ret;
6244
6245 return len;
6246}
6247
6248
6249int wpa_get_mib_sta(struct wpa_state_machine *sm, char *buf, size_t buflen)
6250{
6251 int len = 0, ret;
6252 u32 pairwise = 0;
6253
Hai Shalomfdcde762020-04-02 11:19:20 -07006254 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006255 return 0;
6256
6257 /* TODO: FF-FF-FF-FF-FF-FF entry for broadcast/multicast stats */
6258
6259 /* dot11RSNAStatsEntry */
6260
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07006261 pairwise = wpa_cipher_to_suite(sm->wpa == WPA_VERSION_WPA2 ?
6262 WPA_PROTO_RSN : WPA_PROTO_WPA,
6263 sm->pairwise);
6264 if (pairwise == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006265 return 0;
6266
6267 ret = os_snprintf(
6268 buf + len, buflen - len,
6269 /* TODO: dot11RSNAStatsIndex */
6270 "dot11RSNAStatsSTAAddress=" MACSTR "\n"
6271 "dot11RSNAStatsVersion=1\n"
6272 "dot11RSNAStatsSelectedPairwiseCipher=" RSN_SUITE "\n"
6273 /* TODO: dot11RSNAStatsTKIPICVErrors */
6274 "dot11RSNAStatsTKIPLocalMICFailures=%u\n"
6275 "dot11RSNAStatsTKIPRemoteMICFailures=%u\n"
6276 /* TODO: dot11RSNAStatsCCMPReplays */
6277 /* TODO: dot11RSNAStatsCCMPDecryptErrors */
6278 /* TODO: dot11RSNAStatsTKIPReplays */,
6279 MAC2STR(sm->addr),
6280 RSN_SUITE_ARG(pairwise),
6281 sm->dot11RSNAStatsTKIPLocalMICFailures,
6282 sm->dot11RSNAStatsTKIPRemoteMICFailures);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006283 if (os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006284 return len;
6285 len += ret;
6286
6287 /* Private MIB */
6288 ret = os_snprintf(buf + len, buflen - len,
Hai Shalomc3565922019-10-28 11:58:20 -07006289 "wpa=%d\n"
6290 "AKMSuiteSelector=" RSN_SUITE "\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006291 "hostapdWPAPTKState=%d\n"
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00006292 "hostapdWPAPTKGroupState=%d\n"
6293 "hostapdMFPR=%d\n",
Hai Shalomc3565922019-10-28 11:58:20 -07006294 sm->wpa,
6295 RSN_SUITE_ARG(wpa_akm_to_suite(sm->wpa_key_mgmt)),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006296 sm->wpa_ptk_state,
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00006297 sm->wpa_ptk_group_state,
6298 sm->mfpr);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006299 if (os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006300 return len;
6301 len += ret;
6302
6303 return len;
6304}
6305
6306
6307void wpa_auth_countermeasures_start(struct wpa_authenticator *wpa_auth)
6308{
6309 if (wpa_auth)
6310 wpa_auth->dot11RSNATKIPCounterMeasuresInvoked++;
6311}
6312
6313
6314int wpa_auth_pairwise_set(struct wpa_state_machine *sm)
6315{
6316 return sm && sm->pairwise_set;
6317}
6318
6319
6320int wpa_auth_get_pairwise(struct wpa_state_machine *sm)
6321{
6322 return sm->pairwise;
6323}
6324
6325
Hai Shalom74f70d42019-02-11 14:42:39 -08006326const u8 * wpa_auth_get_pmk(struct wpa_state_machine *sm, int *len)
6327{
6328 if (!sm)
6329 return NULL;
6330 *len = sm->pmk_len;
6331 return sm->PMK;
6332}
6333
6334
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00006335const u8 * wpa_auth_get_dpp_pkhash(struct wpa_state_machine *sm)
6336{
6337 if (!sm || !sm->pmksa)
6338 return NULL;
6339 return sm->pmksa->dpp_pkhash;
6340}
6341
6342
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006343int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm)
6344{
Hai Shalomfdcde762020-04-02 11:19:20 -07006345 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006346 return -1;
6347 return sm->wpa_key_mgmt;
6348}
6349
6350
6351int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm)
6352{
Hai Shalomfdcde762020-04-02 11:19:20 -07006353 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006354 return 0;
6355 return sm->wpa;
6356}
6357
6358
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02006359int wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm)
6360{
6361 if (!sm || !wpa_key_mgmt_ft(sm->wpa_key_mgmt))
6362 return 0;
6363 return sm->tk_already_set;
6364}
6365
6366
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006367int wpa_auth_sta_fils_tk_already_set(struct wpa_state_machine *sm)
6368{
6369 if (!sm || !wpa_key_mgmt_fils(sm->wpa_key_mgmt))
6370 return 0;
6371 return sm->tk_already_set;
6372}
6373
6374
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006375int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm,
6376 struct rsn_pmksa_cache_entry *entry)
6377{
Hai Shalomfdcde762020-04-02 11:19:20 -07006378 if (!sm || sm->pmksa != entry)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006379 return -1;
6380 sm->pmksa = NULL;
6381 return 0;
6382}
6383
6384
6385struct rsn_pmksa_cache_entry *
6386wpa_auth_sta_get_pmksa(struct wpa_state_machine *sm)
6387{
6388 return sm ? sm->pmksa : NULL;
6389}
6390
6391
6392void wpa_auth_sta_local_mic_failure_report(struct wpa_state_machine *sm)
6393{
6394 if (sm)
6395 sm->dot11RSNAStatsTKIPLocalMICFailures++;
6396}
6397
6398
6399const u8 * wpa_auth_get_wpa_ie(struct wpa_authenticator *wpa_auth, size_t *len)
6400{
Hai Shalomfdcde762020-04-02 11:19:20 -07006401 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006402 return NULL;
6403 *len = wpa_auth->wpa_ie_len;
6404 return wpa_auth->wpa_ie;
6405}
6406
6407
6408int wpa_auth_pmksa_add(struct wpa_state_machine *sm, const u8 *pmk,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006409 unsigned int pmk_len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006410 int session_timeout, struct eapol_state_machine *eapol)
6411{
Hai Shalomfdcde762020-04-02 11:19:20 -07006412 if (!sm || sm->wpa != WPA_VERSION_WPA2 ||
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07006413 sm->wpa_auth->conf.disable_pmksa_caching)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006414 return -1;
6415
Hai Shalom81f62d82019-07-22 12:10:00 -07006416#ifdef CONFIG_IEEE80211R_AP
6417 if (pmk_len >= 2 * PMK_LEN && wpa_key_mgmt_ft(sm->wpa_key_mgmt) &&
6418 wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) &&
6419 !wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) {
6420 /* Cache MPMK/XXKey instead of initial part from MSK */
6421 pmk = pmk + PMK_LEN;
6422 pmk_len = PMK_LEN;
6423 } else
6424#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006425 if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006426 if (pmk_len > PMK_LEN_SUITE_B_192)
6427 pmk_len = PMK_LEN_SUITE_B_192;
6428 } else if (pmk_len > PMK_LEN) {
6429 pmk_len = PMK_LEN;
6430 }
6431
Hai Shalom81f62d82019-07-22 12:10:00 -07006432 wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK", pmk, pmk_len);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006433 if (pmksa_cache_auth_add(sm->wpa_auth->pmksa, pmk, pmk_len, NULL,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08006434 sm->PTK.kck, sm->PTK.kck_len,
Sunil Raviaf8751c2023-03-29 11:35:17 -07006435 wpa_auth_get_aa(sm),
6436 wpa_auth_get_spa(sm), session_timeout,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006437 eapol, sm->wpa_key_mgmt))
6438 return 0;
6439
6440 return -1;
6441}
6442
6443
6444int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth,
6445 const u8 *pmk, size_t len, const u8 *sta_addr,
6446 int session_timeout,
6447 struct eapol_state_machine *eapol)
6448{
Hai Shalomfdcde762020-04-02 11:19:20 -07006449 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006450 return -1;
6451
Hai Shalom81f62d82019-07-22 12:10:00 -07006452 wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK from preauth", pmk, len);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006453 if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, len, NULL,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006454 NULL, 0,
6455 wpa_auth->addr,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006456 sta_addr, session_timeout, eapol,
6457 WPA_KEY_MGMT_IEEE8021X))
6458 return 0;
6459
6460 return -1;
6461}
6462
6463
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006464int wpa_auth_pmksa_add_sae(struct wpa_authenticator *wpa_auth, const u8 *addr,
Sunil Ravi89eba102022-09-13 21:04:37 -07006465 const u8 *pmk, size_t pmk_len, const u8 *pmkid,
6466 int akmp)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006467{
6468 if (wpa_auth->conf.disable_pmksa_caching)
6469 return -1;
6470
Sunil Ravi89eba102022-09-13 21:04:37 -07006471 wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK from SAE", pmk, pmk_len);
6472 if (!akmp)
6473 akmp = WPA_KEY_MGMT_SAE;
6474 if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, pmk_len, pmkid,
6475 NULL, 0, wpa_auth->addr, addr, 0, NULL, akmp))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006476 return 0;
6477
6478 return -1;
6479}
6480
6481
Roshan Pius3a1667e2018-07-03 15:17:14 -07006482void wpa_auth_add_sae_pmkid(struct wpa_state_machine *sm, const u8 *pmkid)
6483{
6484 os_memcpy(sm->pmkid, pmkid, PMKID_LEN);
6485 sm->pmkid_set = 1;
6486}
6487
6488
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006489int wpa_auth_pmksa_add2(struct wpa_authenticator *wpa_auth, const u8 *addr,
6490 const u8 *pmk, size_t pmk_len, const u8 *pmkid,
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00006491 int session_timeout, int akmp, const u8 *dpp_pkhash)
6492{
6493 struct rsn_pmksa_cache_entry *entry;
6494
Sunil Ravib0ac25f2024-07-12 01:42:03 +00006495 if (!wpa_auth || wpa_auth->conf.disable_pmksa_caching)
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00006496 return -1;
6497
6498 wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK (3)", pmk, PMK_LEN);
6499 entry = pmksa_cache_auth_add(wpa_auth->pmksa, pmk, pmk_len, pmkid,
6500 NULL, 0, wpa_auth->addr, addr, session_timeout,
6501 NULL, akmp);
6502 if (!entry)
6503 return -1;
6504
6505 if (dpp_pkhash)
6506 entry->dpp_pkhash = os_memdup(dpp_pkhash, SHA256_MAC_LEN);
6507
6508 return 0;
6509}
6510
6511
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07006512void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth,
6513 const u8 *sta_addr)
6514{
6515 struct rsn_pmksa_cache_entry *pmksa;
6516
Hai Shalomfdcde762020-04-02 11:19:20 -07006517 if (!wpa_auth || !wpa_auth->pmksa)
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07006518 return;
6519 pmksa = pmksa_cache_auth_get(wpa_auth->pmksa, sta_addr, NULL);
6520 if (pmksa) {
6521 wpa_printf(MSG_DEBUG, "WPA: Remove PMKSA cache entry for "
6522 MACSTR " based on request", MAC2STR(sta_addr));
6523 pmksa_cache_free_entry(wpa_auth->pmksa, pmksa);
6524 }
6525}
6526
6527
Dmitry Shmidte4663042016-04-04 10:07:49 -07006528int wpa_auth_pmksa_list(struct wpa_authenticator *wpa_auth, char *buf,
6529 size_t len)
6530{
6531 if (!wpa_auth || !wpa_auth->pmksa)
6532 return 0;
6533 return pmksa_cache_auth_list(wpa_auth->pmksa, buf, len);
6534}
6535
6536
6537void wpa_auth_pmksa_flush(struct wpa_authenticator *wpa_auth)
6538{
6539 if (wpa_auth && wpa_auth->pmksa)
6540 pmksa_cache_auth_flush(wpa_auth->pmksa);
6541}
6542
6543
Paul Stewart092955c2017-02-06 09:13:09 -08006544#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
6545#ifdef CONFIG_MESH
6546
6547int wpa_auth_pmksa_list_mesh(struct wpa_authenticator *wpa_auth, const u8 *addr,
6548 char *buf, size_t len)
6549{
6550 if (!wpa_auth || !wpa_auth->pmksa)
6551 return 0;
6552
6553 return pmksa_cache_auth_list_mesh(wpa_auth->pmksa, addr, buf, len);
6554}
6555
6556
6557struct rsn_pmksa_cache_entry *
6558wpa_auth_pmksa_create_entry(const u8 *aa, const u8 *spa, const u8 *pmk,
Sunil Ravi89eba102022-09-13 21:04:37 -07006559 size_t pmk_len, int akmp,
Paul Stewart092955c2017-02-06 09:13:09 -08006560 const u8 *pmkid, int expiration)
6561{
6562 struct rsn_pmksa_cache_entry *entry;
6563 struct os_reltime now;
6564
Sunil Ravi89eba102022-09-13 21:04:37 -07006565 entry = pmksa_cache_auth_create_entry(pmk, pmk_len, pmkid, NULL, 0, aa,
6566 spa, 0, NULL, akmp);
Paul Stewart092955c2017-02-06 09:13:09 -08006567 if (!entry)
6568 return NULL;
6569
6570 os_get_reltime(&now);
6571 entry->expiration = now.sec + expiration;
6572 return entry;
6573}
6574
6575
6576int wpa_auth_pmksa_add_entry(struct wpa_authenticator *wpa_auth,
6577 struct rsn_pmksa_cache_entry *entry)
6578{
6579 int ret;
6580
6581 if (!wpa_auth || !wpa_auth->pmksa)
6582 return -1;
6583
6584 ret = pmksa_cache_auth_add_entry(wpa_auth->pmksa, entry);
6585 if (ret < 0)
6586 wpa_printf(MSG_DEBUG,
6587 "RSN: Failed to store external PMKSA cache for "
6588 MACSTR, MAC2STR(entry->spa));
6589
6590 return ret;
6591}
6592
6593#endif /* CONFIG_MESH */
6594#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
6595
6596
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00006597struct rsn_pmksa_cache *
6598wpa_auth_get_pmksa_cache(struct wpa_authenticator *wpa_auth)
6599{
6600 if (!wpa_auth || !wpa_auth->pmksa)
6601 return NULL;
6602 return wpa_auth->pmksa;
6603}
6604
6605
Dmitry Shmidte4663042016-04-04 10:07:49 -07006606struct rsn_pmksa_cache_entry *
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08006607wpa_auth_pmksa_get(struct wpa_authenticator *wpa_auth, const u8 *sta_addr,
6608 const u8 *pmkid)
Dmitry Shmidte4663042016-04-04 10:07:49 -07006609{
6610 if (!wpa_auth || !wpa_auth->pmksa)
6611 return NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08006612 return pmksa_cache_auth_get(wpa_auth->pmksa, sta_addr, pmkid);
Dmitry Shmidte4663042016-04-04 10:07:49 -07006613}
6614
6615
6616void wpa_auth_pmksa_set_to_sm(struct rsn_pmksa_cache_entry *pmksa,
6617 struct wpa_state_machine *sm,
6618 struct wpa_authenticator *wpa_auth,
Sunil Ravib0ac25f2024-07-12 01:42:03 +00006619 u8 *pmkid, u8 *pmk, size_t *pmk_len)
Dmitry Shmidte4663042016-04-04 10:07:49 -07006620{
6621 if (!sm)
6622 return;
6623
6624 sm->pmksa = pmksa;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00006625 os_memcpy(pmk, pmksa->pmk, pmksa->pmk_len);
6626 *pmk_len = pmksa->pmk_len;
Dmitry Shmidte4663042016-04-04 10:07:49 -07006627 os_memcpy(pmkid, pmksa->pmkid, PMKID_LEN);
6628 os_memcpy(wpa_auth->dot11RSNAPMKIDUsed, pmksa->pmkid, PMKID_LEN);
6629}
6630
6631
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07006632/*
6633 * Remove and free the group from wpa_authenticator. This is triggered by a
6634 * callback to make sure nobody is currently iterating the group list while it
6635 * gets modified.
6636 */
6637static void wpa_group_free(struct wpa_authenticator *wpa_auth,
6638 struct wpa_group *group)
6639{
6640 struct wpa_group *prev = wpa_auth->group;
6641
6642 wpa_printf(MSG_DEBUG, "WPA: Remove group state machine for VLAN-ID %d",
6643 group->vlan_id);
6644
6645 while (prev) {
6646 if (prev->next == group) {
6647 /* This never frees the special first group as needed */
6648 prev->next = group->next;
6649 os_free(group);
6650 break;
6651 }
6652 prev = prev->next;
6653 }
6654
6655}
6656
6657
6658/* Increase the reference counter for group */
6659static void wpa_group_get(struct wpa_authenticator *wpa_auth,
6660 struct wpa_group *group)
6661{
6662 /* Skip the special first group */
6663 if (wpa_auth->group == group)
6664 return;
6665
6666 group->references++;
6667}
6668
6669
6670/* Decrease the reference counter and maybe free the group */
6671static void wpa_group_put(struct wpa_authenticator *wpa_auth,
6672 struct wpa_group *group)
6673{
6674 /* Skip the special first group */
6675 if (wpa_auth->group == group)
6676 return;
6677
6678 group->references--;
6679 if (group->references)
6680 return;
6681 wpa_group_free(wpa_auth, group);
6682}
6683
6684
6685/*
6686 * Add a group that has its references counter set to zero. Caller needs to
6687 * call wpa_group_get() on the return value to mark the entry in use.
6688 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006689static struct wpa_group *
6690wpa_auth_add_group(struct wpa_authenticator *wpa_auth, int vlan_id)
6691{
6692 struct wpa_group *group;
6693
Hai Shalomfdcde762020-04-02 11:19:20 -07006694 if (!wpa_auth || !wpa_auth->group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006695 return NULL;
6696
6697 wpa_printf(MSG_DEBUG, "WPA: Add group state machine for VLAN-ID %d",
6698 vlan_id);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006699 group = wpa_group_init(wpa_auth, vlan_id, 0);
Hai Shalomfdcde762020-04-02 11:19:20 -07006700 if (!group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006701 return NULL;
6702
6703 group->next = wpa_auth->group->next;
6704 wpa_auth->group->next = group;
6705
6706 return group;
6707}
6708
6709
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006710/*
6711 * Enforce that the group state machine for the VLAN is running, increase
6712 * reference counter as interface is up. References might have been increased
6713 * even if a negative value is returned.
6714 * Returns: -1 on error (group missing, group already failed); otherwise, 0
6715 */
6716int wpa_auth_ensure_group(struct wpa_authenticator *wpa_auth, int vlan_id)
6717{
6718 struct wpa_group *group;
6719
Hai Shalomfdcde762020-04-02 11:19:20 -07006720 if (!wpa_auth)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006721 return 0;
6722
6723 group = wpa_auth->group;
6724 while (group) {
6725 if (group->vlan_id == vlan_id)
6726 break;
6727 group = group->next;
6728 }
6729
Hai Shalomfdcde762020-04-02 11:19:20 -07006730 if (!group) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006731 group = wpa_auth_add_group(wpa_auth, vlan_id);
Hai Shalomfdcde762020-04-02 11:19:20 -07006732 if (!group)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006733 return -1;
6734 }
6735
6736 wpa_printf(MSG_DEBUG,
6737 "WPA: Ensure group state machine running for VLAN ID %d",
6738 vlan_id);
6739
6740 wpa_group_get(wpa_auth, group);
6741 group->num_setup_iface++;
6742
6743 if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
6744 return -1;
6745
6746 return 0;
6747}
6748
6749
6750/*
6751 * Decrease reference counter, expected to be zero afterwards.
6752 * returns: -1 on error (group not found, group in fail state)
6753 * -2 if wpa_group is still referenced
6754 * 0 else
6755 */
6756int wpa_auth_release_group(struct wpa_authenticator *wpa_auth, int vlan_id)
6757{
6758 struct wpa_group *group;
6759 int ret = 0;
6760
Hai Shalomfdcde762020-04-02 11:19:20 -07006761 if (!wpa_auth)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006762 return 0;
6763
6764 group = wpa_auth->group;
6765 while (group) {
6766 if (group->vlan_id == vlan_id)
6767 break;
6768 group = group->next;
6769 }
6770
Hai Shalomfdcde762020-04-02 11:19:20 -07006771 if (!group)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006772 return -1;
6773
6774 wpa_printf(MSG_DEBUG,
6775 "WPA: Try stopping group state machine for VLAN ID %d",
6776 vlan_id);
6777
6778 if (group->num_setup_iface <= 0) {
6779 wpa_printf(MSG_ERROR,
6780 "WPA: wpa_auth_release_group called more often than wpa_auth_ensure_group for VLAN ID %d, skipping.",
6781 vlan_id);
6782 return -1;
6783 }
6784 group->num_setup_iface--;
6785
6786 if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
6787 ret = -1;
6788
6789 if (group->references > 1) {
6790 wpa_printf(MSG_DEBUG,
6791 "WPA: Cannot stop group state machine for VLAN ID %d as references are still hold",
6792 vlan_id);
6793 ret = -2;
6794 }
6795
6796 wpa_group_put(wpa_auth, group);
6797
6798 return ret;
6799}
6800
6801
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006802int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id)
6803{
6804 struct wpa_group *group;
6805
Hai Shalomfdcde762020-04-02 11:19:20 -07006806 if (!sm || !sm->wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006807 return 0;
6808
6809 group = sm->wpa_auth->group;
6810 while (group) {
6811 if (group->vlan_id == vlan_id)
6812 break;
6813 group = group->next;
6814 }
6815
Hai Shalomfdcde762020-04-02 11:19:20 -07006816 if (!group) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006817 group = wpa_auth_add_group(sm->wpa_auth, vlan_id);
Hai Shalomfdcde762020-04-02 11:19:20 -07006818 if (!group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006819 return -1;
6820 }
6821
6822 if (sm->group == group)
6823 return 0;
6824
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006825 if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
6826 return -1;
6827
Hai Shalomfdcde762020-04-02 11:19:20 -07006828 wpa_printf(MSG_DEBUG, "WPA: Moving STA " MACSTR
6829 " to use group state machine for VLAN ID %d",
Sunil Raviaf8751c2023-03-29 11:35:17 -07006830 MAC2STR(wpa_auth_get_spa(sm)), vlan_id);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006831
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07006832 wpa_group_get(sm->wpa_auth, group);
6833 wpa_group_put(sm->wpa_auth, sm->group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006834 sm->group = group;
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07006835
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006836 return 0;
6837}
6838
6839
6840void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth,
6841 struct wpa_state_machine *sm, int ack)
6842{
Hai Shalomfdcde762020-04-02 11:19:20 -07006843 if (!wpa_auth || !sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006844 return;
6845 wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key TX status for STA " MACSTR
Sunil Raviaf8751c2023-03-29 11:35:17 -07006846 " ack=%d", MAC2STR(wpa_auth_get_spa(sm)), ack);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006847 if (sm->pending_1_of_4_timeout && ack) {
6848 /*
6849 * Some deployed supplicant implementations update their SNonce
6850 * for each EAPOL-Key 2/4 message even within the same 4-way
6851 * handshake and then fail to use the first SNonce when
6852 * deriving the PTK. This results in unsuccessful 4-way
6853 * handshake whenever the relatively short initial timeout is
6854 * reached and EAPOL-Key 1/4 is retransmitted. Try to work
6855 * around this by increasing the timeout now that we know that
6856 * the station has received the frame.
6857 */
6858 int timeout_ms = eapol_key_timeout_subseq;
Hai Shalomfdcde762020-04-02 11:19:20 -07006859 wpa_printf(MSG_DEBUG,
6860 "WPA: Increase initial EAPOL-Key 1/4 timeout by %u ms because of acknowledged frame",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006861 timeout_ms);
6862 eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm);
6863 eloop_register_timeout(timeout_ms / 1000,
6864 (timeout_ms % 1000) * 1000,
6865 wpa_send_eapol_timeout, wpa_auth, sm);
6866 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006867
6868#ifdef CONFIG_TESTING_OPTIONS
6869 if (sm->eapol_status_cb) {
6870 sm->eapol_status_cb(sm->eapol_status_cb_ctx1,
6871 sm->eapol_status_cb_ctx2);
6872 sm->eapol_status_cb = NULL;
6873 }
6874#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006875}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006876
6877
6878int wpa_auth_uses_sae(struct wpa_state_machine *sm)
6879{
Hai Shalomfdcde762020-04-02 11:19:20 -07006880 if (!sm)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006881 return 0;
6882 return wpa_key_mgmt_sae(sm->wpa_key_mgmt);
6883}
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006884
6885
6886int wpa_auth_uses_ft_sae(struct wpa_state_machine *sm)
6887{
Hai Shalomfdcde762020-04-02 11:19:20 -07006888 if (!sm)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006889 return 0;
Sunil Ravi89eba102022-09-13 21:04:37 -07006890 return sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_SAE ||
6891 sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_SAE_EXT_KEY;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006892}
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08006893
6894
6895#ifdef CONFIG_P2P
6896int wpa_auth_get_ip_addr(struct wpa_state_machine *sm, u8 *addr)
6897{
Hai Shalomfdcde762020-04-02 11:19:20 -07006898 if (!sm || WPA_GET_BE32(sm->ip_addr) == 0)
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08006899 return -1;
6900 os_memcpy(addr, sm->ip_addr, 4);
6901 return 0;
6902}
6903#endif /* CONFIG_P2P */
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08006904
6905
6906int wpa_auth_radius_das_disconnect_pmksa(struct wpa_authenticator *wpa_auth,
6907 struct radius_das_attrs *attr)
6908{
6909 return pmksa_cache_auth_radius_das_disconnect(wpa_auth->pmksa, attr);
6910}
Dmitry Shmidt7f656022015-02-25 14:36:37 -08006911
6912
6913void wpa_auth_reconfig_group_keys(struct wpa_authenticator *wpa_auth)
6914{
6915 struct wpa_group *group;
6916
6917 if (!wpa_auth)
6918 return;
6919 for (group = wpa_auth->group; group; group = group->next)
6920 wpa_group_config_group_keys(wpa_auth, group);
6921}
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006922
6923
6924#ifdef CONFIG_FILS
6925
6926struct wpa_auth_fils_iter_data {
6927 struct wpa_authenticator *auth;
6928 const u8 *cache_id;
6929 struct rsn_pmksa_cache_entry *pmksa;
6930 const u8 *spa;
6931 const u8 *pmkid;
6932};
6933
6934
6935static int wpa_auth_fils_iter(struct wpa_authenticator *a, void *ctx)
6936{
6937 struct wpa_auth_fils_iter_data *data = ctx;
6938
6939 if (a == data->auth || !a->conf.fils_cache_id_set ||
6940 os_memcmp(a->conf.fils_cache_id, data->cache_id,
6941 FILS_CACHE_ID_LEN) != 0)
6942 return 0;
6943 data->pmksa = pmksa_cache_auth_get(a->pmksa, data->spa, data->pmkid);
6944 return data->pmksa != NULL;
6945}
6946
6947
6948struct rsn_pmksa_cache_entry *
6949wpa_auth_pmksa_get_fils_cache_id(struct wpa_authenticator *wpa_auth,
6950 const u8 *sta_addr, const u8 *pmkid)
6951{
6952 struct wpa_auth_fils_iter_data idata;
6953
6954 if (!wpa_auth->conf.fils_cache_id_set)
6955 return NULL;
6956 idata.auth = wpa_auth;
6957 idata.cache_id = wpa_auth->conf.fils_cache_id;
6958 idata.pmksa = NULL;
6959 idata.spa = sta_addr;
6960 idata.pmkid = pmkid;
6961 wpa_auth_for_each_auth(wpa_auth, wpa_auth_fils_iter, &idata);
6962 return idata.pmksa;
6963}
6964
6965
6966#ifdef CONFIG_IEEE80211R_AP
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00006967int wpa_auth_write_fte(struct wpa_authenticator *wpa_auth,
6968 struct wpa_state_machine *sm,
Roshan Pius3a1667e2018-07-03 15:17:14 -07006969 u8 *buf, size_t len)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006970{
6971 struct wpa_auth_config *conf = &wpa_auth->conf;
6972
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00006973 return wpa_write_ftie(conf, sm->wpa_key_mgmt, sm->xxkey_len,
6974 conf->r0_key_holder, conf->r0_key_holder_len,
Hai Shalomfdcde762020-04-02 11:19:20 -07006975 NULL, NULL, buf, len, NULL, 0, 0);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006976}
6977#endif /* CONFIG_IEEE80211R_AP */
6978
6979
6980void wpa_auth_get_fils_aead_params(struct wpa_state_machine *sm,
6981 u8 *fils_anonce, u8 *fils_snonce,
6982 u8 *fils_kek, size_t *fils_kek_len)
6983{
6984 os_memcpy(fils_anonce, sm->ANonce, WPA_NONCE_LEN);
6985 os_memcpy(fils_snonce, sm->SNonce, WPA_NONCE_LEN);
6986 os_memcpy(fils_kek, sm->PTK.kek, WPA_KEK_MAX_LEN);
6987 *fils_kek_len = sm->PTK.kek_len;
6988}
6989
Hai Shalom81f62d82019-07-22 12:10:00 -07006990
6991void wpa_auth_add_fils_pmk_pmkid(struct wpa_state_machine *sm, const u8 *pmk,
6992 size_t pmk_len, const u8 *pmkid)
6993{
6994 os_memcpy(sm->PMK, pmk, pmk_len);
6995 sm->pmk_len = pmk_len;
6996 os_memcpy(sm->pmkid, pmkid, PMKID_LEN);
6997 sm->pmkid_set = 1;
6998}
6999
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007000#endif /* CONFIG_FILS */
7001
7002
Hai Shalom021b0b52019-04-10 11:17:58 -07007003void wpa_auth_set_auth_alg(struct wpa_state_machine *sm, u16 auth_alg)
7004{
7005 if (sm)
7006 sm->auth_alg = auth_alg;
7007}
7008
7009
Sunil Ravic0f5d412024-09-11 22:12:49 +00007010void wpa_auth_set_rsn_selection(struct wpa_state_machine *sm, const u8 *ie,
7011 size_t len)
Sunil Ravi7f769292024-07-23 22:21:32 +00007012{
Sunil Ravic0f5d412024-09-11 22:12:49 +00007013 if (!sm)
7014 return;
7015 os_free(sm->rsn_selection);
7016 sm->rsn_selection = NULL;
7017 sm->rsn_selection_len = 0;
7018 sm->rsn_override = false;
7019 sm->rsn_override_2 = false;
7020 if (ie) {
7021 if (len >= 1) {
7022 if (ie[0] == RSN_SELECTION_RSNE_OVERRIDE)
7023 sm->rsn_override = true;
7024 else if (ie[0] == RSN_SELECTION_RSNE_OVERRIDE_2)
7025 sm->rsn_override_2 = true;
7026 }
7027 sm->rsn_selection = os_memdup(ie, len);
7028 if (sm->rsn_selection)
7029 sm->rsn_selection_len = len;
7030 }
Sunil Ravi7f769292024-07-23 22:21:32 +00007031}
7032
7033
Hai Shalom021b0b52019-04-10 11:17:58 -07007034#ifdef CONFIG_DPP2
7035void wpa_auth_set_dpp_z(struct wpa_state_machine *sm, const struct wpabuf *z)
7036{
7037 if (sm) {
7038 wpabuf_clear_free(sm->dpp_z);
7039 sm->dpp_z = z ? wpabuf_dup(z) : NULL;
7040 }
7041}
7042#endif /* CONFIG_DPP2 */
7043
7044
Sunil Ravi7f769292024-07-23 22:21:32 +00007045void wpa_auth_set_ssid_protection(struct wpa_state_machine *sm, bool val)
7046{
7047 if (sm)
7048 sm->ssid_protection = val;
7049}
7050
7051
Hai Shalom899fcc72020-10-19 14:38:18 -07007052void wpa_auth_set_transition_disable(struct wpa_authenticator *wpa_auth,
7053 u8 val)
7054{
7055 if (wpa_auth)
7056 wpa_auth->conf.transition_disable = val;
7057}
7058
7059
Roshan Pius3a1667e2018-07-03 15:17:14 -07007060#ifdef CONFIG_TESTING_OPTIONS
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007061
7062int wpa_auth_resend_m1(struct wpa_state_machine *sm, int change_anonce,
7063 void (*cb)(void *ctx1, void *ctx2),
7064 void *ctx1, void *ctx2)
7065{
7066 const u8 *anonce = sm->ANonce;
7067 u8 anonce_buf[WPA_NONCE_LEN];
7068
7069 if (change_anonce) {
7070 if (random_get_bytes(anonce_buf, WPA_NONCE_LEN))
7071 return -1;
7072 anonce = anonce_buf;
7073 }
7074
Sunil Raviaf8751c2023-03-29 11:35:17 -07007075 wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007076 "sending 1/4 msg of 4-Way Handshake (TESTING)");
7077 wpa_send_eapol(sm->wpa_auth, sm,
7078 WPA_KEY_INFO_ACK | WPA_KEY_INFO_KEY_TYPE, NULL,
7079 anonce, NULL, 0, 0, 0);
7080 return 0;
7081}
7082
7083
7084int wpa_auth_resend_m3(struct wpa_state_machine *sm,
7085 void (*cb)(void *ctx1, void *ctx2),
7086 void *ctx1, void *ctx2)
7087{
Roshan Pius3a1667e2018-07-03 15:17:14 -07007088 u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde, *pos;
Roshan Pius3a1667e2018-07-03 15:17:14 -07007089 u8 *opos;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007090 size_t gtk_len, kde_len;
Hai Shalom899fcc72020-10-19 14:38:18 -07007091 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007092 struct wpa_group *gsm = sm->group;
7093 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07007094 int wpa_ie_len, secure, gtkidx, encr = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07007095 u8 hdr[2];
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007096
7097 /* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, [MDIE],
Hai Shalomfdcde762020-04-02 11:19:20 -07007098 GTK[GN], IGTK, [BIGTK], [FTIE], [TIE * 2])
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007099 */
7100
7101 /* Use 0 RSC */
7102 os_memset(rsc, 0, WPA_KEY_RSC_LEN);
7103 /* If FT is used, wpa_auth->wpa_ie includes both RSNIE and MDIE */
7104 wpa_ie = sm->wpa_auth->wpa_ie;
7105 wpa_ie_len = sm->wpa_auth->wpa_ie_len;
7106 if (sm->wpa == WPA_VERSION_WPA &&
7107 (sm->wpa_auth->conf.wpa & WPA_PROTO_RSN) &&
7108 wpa_ie_len > wpa_ie[1] + 2 && wpa_ie[0] == WLAN_EID_RSN) {
7109 /* WPA-only STA, remove RSN IE and possible MDIE */
7110 wpa_ie = wpa_ie + wpa_ie[1] + 2;
Hai Shalom60840252021-02-19 19:02:11 -08007111 if (wpa_ie[0] == WLAN_EID_RSNX)
7112 wpa_ie = wpa_ie + wpa_ie[1] + 2;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007113 if (wpa_ie[0] == WLAN_EID_MOBILITY_DOMAIN)
7114 wpa_ie = wpa_ie + wpa_ie[1] + 2;
7115 wpa_ie_len = wpa_ie[1] + 2;
7116 }
Sunil Raviaf8751c2023-03-29 11:35:17 -07007117 wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007118 "sending 3/4 msg of 4-Way Handshake (TESTING)");
7119 if (sm->wpa == WPA_VERSION_WPA2) {
7120 /* WPA2 send GTK in the 4-way handshake */
7121 secure = 1;
7122 gtk = gsm->GTK[gsm->GN - 1];
7123 gtk_len = gsm->GTK_len;
Hai Shalomc3565922019-10-28 11:58:20 -07007124 gtkidx = gsm->GN;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007125 _rsc = rsc;
7126 encr = 1;
7127 } else {
7128 /* WPA does not include GTK in msg 3/4 */
7129 secure = 0;
7130 gtk = NULL;
7131 gtk_len = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007132 _rsc = NULL;
7133 if (sm->rx_eapol_key_secure) {
7134 /*
7135 * It looks like Windows 7 supplicant tries to use
7136 * Secure bit in msg 2/4 after having reported Michael
7137 * MIC failure and it then rejects the 4-way handshake
7138 * if msg 3/4 does not set Secure bit. Work around this
7139 * by setting the Secure bit here even in the case of
7140 * WPA if the supplicant used it first.
7141 */
Sunil Raviaf8751c2023-03-29 11:35:17 -07007142 wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm),
7143 LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07007144 "STA used Secure bit in WPA msg 2/4 - set Secure for 3/4 as workaround");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007145 secure = 1;
7146 }
7147 }
7148
Hai Shalom74f70d42019-02-11 14:42:39 -08007149 kde_len = wpa_ie_len + ieee80211w_kde_len(sm) + ocv_oci_len(sm);
Hai Shalomfdcde762020-04-02 11:19:20 -07007150
7151 if (sm->use_ext_key_id)
7152 kde_len += 2 + RSN_SELECTOR_LEN + 2;
7153
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007154 if (gtk)
7155 kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len;
7156#ifdef CONFIG_IEEE80211R_AP
7157 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
7158 kde_len += 2 + PMKID_LEN; /* PMKR1Name into RSN IE */
7159 kde_len += 300; /* FTIE + 2 * TIE */
7160 }
7161#endif /* CONFIG_IEEE80211R_AP */
7162 kde = os_malloc(kde_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07007163 if (!kde)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007164 return -1;
7165
7166 pos = kde;
7167 os_memcpy(pos, wpa_ie, wpa_ie_len);
7168 pos += wpa_ie_len;
7169#ifdef CONFIG_IEEE80211R_AP
7170 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
7171 int res;
7172 size_t elen;
7173
7174 elen = pos - kde;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00007175 res = wpa_insert_pmkid(kde, &elen, sm->pmk_r1_name, true);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007176 if (res < 0) {
Hai Shalomfdcde762020-04-02 11:19:20 -07007177 wpa_printf(MSG_ERROR,
7178 "FT: Failed to insert PMKR1Name into RSN IE in EAPOL-Key data");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007179 os_free(kde);
7180 return -1;
7181 }
7182 pos -= wpa_ie_len;
7183 pos += elen;
7184 }
7185#endif /* CONFIG_IEEE80211R_AP */
Hai Shalomfdcde762020-04-02 11:19:20 -07007186 hdr[1] = 0;
7187
7188 if (sm->use_ext_key_id) {
7189 hdr[0] = sm->keyidx_active & 0x01;
7190 pos = wpa_add_kde(pos, RSN_KEY_DATA_KEYID, hdr, 2, NULL, 0);
7191 }
7192
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007193 if (gtk) {
Hai Shalomc3565922019-10-28 11:58:20 -07007194 hdr[0] = gtkidx & 0x03;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007195 pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
7196 gtk, gtk_len);
7197 }
7198 opos = pos;
7199 pos = ieee80211w_kde_add(sm, pos);
Roshan Pius3a1667e2018-07-03 15:17:14 -07007200 if (pos - opos >= 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN) {
7201 /* skip KDE header and keyid */
7202 opos += 2 + RSN_SELECTOR_LEN + 2;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007203 os_memset(opos, 0, 6); /* clear PN */
7204 }
Hai Shalom899fcc72020-10-19 14:38:18 -07007205 if (ocv_oci_add(sm, &pos, conf->oci_freq_override_eapol_m3) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -08007206 os_free(kde);
7207 return -1;
7208 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007209
7210#ifdef CONFIG_IEEE80211R_AP
7211 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
7212 int res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007213
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007214 if (sm->assoc_resp_ftie &&
7215 kde + kde_len - pos >= 2 + sm->assoc_resp_ftie[1]) {
7216 os_memcpy(pos, sm->assoc_resp_ftie,
7217 2 + sm->assoc_resp_ftie[1]);
7218 res = 2 + sm->assoc_resp_ftie[1];
7219 } else {
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00007220 res = wpa_write_ftie(conf, sm->wpa_key_mgmt,
7221 sm->xxkey_len,
Roshan Pius3a1667e2018-07-03 15:17:14 -07007222 conf->r0_key_holder,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007223 conf->r0_key_holder_len,
7224 NULL, NULL, pos,
7225 kde + kde_len - pos,
Hai Shalomfdcde762020-04-02 11:19:20 -07007226 NULL, 0, 0);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007227 }
7228 if (res < 0) {
Hai Shalomfdcde762020-04-02 11:19:20 -07007229 wpa_printf(MSG_ERROR,
7230 "FT: Failed to insert FTIE into EAPOL-Key Key Data");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007231 os_free(kde);
7232 return -1;
7233 }
7234 pos += res;
7235
7236 /* TIE[ReassociationDeadline] (TU) */
7237 *pos++ = WLAN_EID_TIMEOUT_INTERVAL;
7238 *pos++ = 5;
7239 *pos++ = WLAN_TIMEOUT_REASSOC_DEADLINE;
7240 WPA_PUT_LE32(pos, conf->reassociation_deadline);
7241 pos += 4;
7242
7243 /* TIE[KeyLifetime] (seconds) */
7244 *pos++ = WLAN_EID_TIMEOUT_INTERVAL;
7245 *pos++ = 5;
7246 *pos++ = WLAN_TIMEOUT_KEY_LIFETIME;
Roshan Pius3a1667e2018-07-03 15:17:14 -07007247 WPA_PUT_LE32(pos, conf->r0_key_lifetime);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007248 pos += 4;
7249 }
7250#endif /* CONFIG_IEEE80211R_AP */
7251
7252 wpa_send_eapol(sm->wpa_auth, sm,
7253 (secure ? WPA_KEY_INFO_SECURE : 0) |
7254 (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
7255 WPA_KEY_INFO_MIC : 0) |
7256 WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL |
7257 WPA_KEY_INFO_KEY_TYPE,
Hai Shalomc3565922019-10-28 11:58:20 -07007258 _rsc, sm->ANonce, kde, pos - kde, 0, encr);
Sunil Ravia04bd252022-05-02 22:54:18 -07007259 bin_clear_free(kde, kde_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007260 return 0;
7261}
7262
7263
7264int wpa_auth_resend_group_m1(struct wpa_state_machine *sm,
7265 void (*cb)(void *ctx1, void *ctx2),
7266 void *ctx1, void *ctx2)
7267{
7268 u8 rsc[WPA_KEY_RSC_LEN];
Hai Shalom899fcc72020-10-19 14:38:18 -07007269 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007270 struct wpa_group *gsm = sm->group;
7271 const u8 *kde;
Roshan Pius3a1667e2018-07-03 15:17:14 -07007272 u8 *kde_buf = NULL, *pos, hdr[2];
Roshan Pius3a1667e2018-07-03 15:17:14 -07007273 u8 *opos;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007274 size_t kde_len;
7275 u8 *gtk;
7276
7277 /* Send EAPOL(1, 1, 1, !Pair, G, RSC, GNonce, MIC(PTK), GTK[GN]) */
7278 os_memset(rsc, 0, WPA_KEY_RSC_LEN);
7279 /* Use 0 RSC */
Sunil Raviaf8751c2023-03-29 11:35:17 -07007280 wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007281 "sending 1/2 msg of Group Key Handshake (TESTING)");
7282
7283 gtk = gsm->GTK[gsm->GN - 1];
7284 if (sm->wpa == WPA_VERSION_WPA2) {
7285 kde_len = 2 + RSN_SELECTOR_LEN + 2 + gsm->GTK_len +
Hai Shalom74f70d42019-02-11 14:42:39 -08007286 ieee80211w_kde_len(sm) + ocv_oci_len(sm);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007287 kde_buf = os_malloc(kde_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07007288 if (!kde_buf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007289 return -1;
7290
7291 kde = pos = kde_buf;
7292 hdr[0] = gsm->GN & 0x03;
7293 hdr[1] = 0;
7294 pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
7295 gtk, gsm->GTK_len);
7296 opos = pos;
7297 pos = ieee80211w_kde_add(sm, pos);
Roshan Pius3a1667e2018-07-03 15:17:14 -07007298 if (pos - opos >=
7299 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN) {
7300 /* skip KDE header and keyid */
7301 opos += 2 + RSN_SELECTOR_LEN + 2;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007302 os_memset(opos, 0, 6); /* clear PN */
7303 }
Hai Shalom899fcc72020-10-19 14:38:18 -07007304 if (ocv_oci_add(sm, &pos,
7305 conf->oci_freq_override_eapol_g1) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -08007306 os_free(kde_buf);
7307 return -1;
7308 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007309 kde_len = pos - kde;
7310 } else {
7311 kde = gtk;
7312 kde_len = gsm->GTK_len;
7313 }
7314
7315 sm->eapol_status_cb = cb;
7316 sm->eapol_status_cb_ctx1 = ctx1;
7317 sm->eapol_status_cb_ctx2 = ctx2;
7318
7319 wpa_send_eapol(sm->wpa_auth, sm,
7320 WPA_KEY_INFO_SECURE |
7321 (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
7322 WPA_KEY_INFO_MIC : 0) |
7323 WPA_KEY_INFO_ACK |
7324 (!sm->Pair ? WPA_KEY_INFO_INSTALL : 0),
7325 rsc, NULL, kde, kde_len, gsm->GN, 1);
7326
Sunil Ravia04bd252022-05-02 22:54:18 -07007327 bin_clear_free(kde_buf, kde_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007328 return 0;
7329}
7330
Roshan Pius3a1667e2018-07-03 15:17:14 -07007331
7332int wpa_auth_rekey_gtk(struct wpa_authenticator *wpa_auth)
7333{
7334 if (!wpa_auth)
7335 return -1;
Sunil Ravi7f769292024-07-23 22:21:32 +00007336 eloop_cancel_timeout(wpa_rekey_gtk,
7337 wpa_get_primary_auth(wpa_auth), NULL);
7338 return eloop_register_timeout(0, 0, wpa_rekey_gtk,
7339 wpa_get_primary_auth(wpa_auth), NULL);
Roshan Pius3a1667e2018-07-03 15:17:14 -07007340}
7341
Hai Shalomb755a2a2020-04-23 21:49:02 -07007342
Hai Shaloma20dcd72022-02-04 13:43:00 -08007343int wpa_auth_rekey_ptk(struct wpa_authenticator *wpa_auth,
7344 struct wpa_state_machine *sm)
7345{
7346 if (!wpa_auth || !sm)
7347 return -1;
7348 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "rekeying PTK");
7349 wpa_request_new_ptk(sm);
7350 wpa_sm_step(sm);
7351 return 0;
7352}
7353
7354
Hai Shalomb755a2a2020-04-23 21:49:02 -07007355void wpa_auth_set_ft_rsnxe_used(struct wpa_authenticator *wpa_auth, int val)
7356{
7357 if (wpa_auth)
7358 wpa_auth->conf.ft_rsnxe_used = val;
7359}
7360
Hai Shalom899fcc72020-10-19 14:38:18 -07007361
7362void wpa_auth_set_ocv_override_freq(struct wpa_authenticator *wpa_auth,
7363 enum wpa_auth_ocv_override_frame frame,
7364 unsigned int freq)
7365{
7366 if (!wpa_auth)
7367 return;
7368 switch (frame) {
7369 case WPA_AUTH_OCV_OVERRIDE_EAPOL_M3:
7370 wpa_auth->conf.oci_freq_override_eapol_m3 = freq;
7371 break;
7372 case WPA_AUTH_OCV_OVERRIDE_EAPOL_G1:
7373 wpa_auth->conf.oci_freq_override_eapol_g1 = freq;
7374 break;
7375 case WPA_AUTH_OCV_OVERRIDE_FT_ASSOC:
7376 wpa_auth->conf.oci_freq_override_ft_assoc = freq;
7377 break;
7378 case WPA_AUTH_OCV_OVERRIDE_FILS_ASSOC:
7379 wpa_auth->conf.oci_freq_override_fils_assoc = freq;
7380 break;
7381 }
7382}
7383
Kai Shie75b0652020-11-24 20:31:29 -08007384void wpa_auth_set_skip_send_eapol(struct wpa_authenticator *wpa_auth,
7385 u8 val)
7386{
7387 if (wpa_auth)
7388 wpa_auth->conf.skip_send_eapol = val;
7389}
7390
7391void wpa_auth_set_enable_eapol_large_timeout(struct wpa_authenticator *wpa_auth,
7392 u8 val)
7393{
7394 if (wpa_auth)
7395 wpa_auth->conf.enable_eapol_large_timeout = val;
7396}
7397
7398
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007399#endif /* CONFIG_TESTING_OPTIONS */
Sunil Ravia04bd252022-05-02 22:54:18 -07007400
7401
7402void wpa_auth_sta_radius_psk_resp(struct wpa_state_machine *sm, bool success)
7403{
7404 if (!sm->waiting_radius_psk) {
7405 wpa_printf(MSG_DEBUG,
7406 "Ignore RADIUS PSK response for " MACSTR
7407 " that did not wait one",
7408 MAC2STR(sm->addr));
7409 return;
7410 }
7411
7412 wpa_printf(MSG_DEBUG, "RADIUS PSK response for " MACSTR " (%s)",
7413 MAC2STR(sm->addr), success ? "success" : "fail");
7414 sm->waiting_radius_psk = 0;
7415
7416 if (success) {
7417 /* Try to process the EAPOL-Key msg 2/4 again */
7418 sm->EAPOLKeyReceived = true;
7419 } else {
7420 sm->Disconnect = true;
7421 }
7422
7423 eloop_register_timeout(0, 0, wpa_sm_call_step, sm, NULL);
7424}
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007425
7426
Sunil Ravi7f769292024-07-23 22:21:32 +00007427void wpa_auth_set_ml_info(struct wpa_state_machine *sm,
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007428 u8 mld_assoc_link_id, struct mld_info *info)
7429{
7430#ifdef CONFIG_IEEE80211BE
Sunil Ravi7f769292024-07-23 22:21:32 +00007431 unsigned int link_id;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007432
7433 if (!info)
7434 return;
7435
7436 os_memset(sm->mld_links, 0, sizeof(sm->mld_links));
Sunil Ravi7f769292024-07-23 22:21:32 +00007437 sm->n_mld_affiliated_links = 0;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007438
7439 wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
7440 "MLD: Initialization");
7441
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007442 os_memcpy(sm->peer_mld_addr, info->common_info.mld_addr, ETH_ALEN);
7443
7444 sm->mld_assoc_link_id = mld_assoc_link_id;
7445
Sunil Ravi7f769292024-07-23 22:21:32 +00007446 for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007447 struct mld_link_info *link = &info->links[link_id];
7448 struct mld_link *sm_link = &sm->mld_links[link_id];
Sunil Ravi7f769292024-07-23 22:21:32 +00007449 struct wpa_get_link_auth_ctx ctx;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007450
7451 sm_link->valid = link->valid;
7452 if (!link->valid)
7453 continue;
7454
7455 os_memcpy(sm_link->peer_addr, link->peer_addr, ETH_ALEN);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007456
7457 wpa_printf(MSG_DEBUG,
Sunil Ravi7f769292024-07-23 22:21:32 +00007458 "WPA_AUTH: MLD: id=%u, peer=" MACSTR,
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007459 link_id,
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007460 MAC2STR(sm_link->peer_addr));
7461
Sunil Ravi7f769292024-07-23 22:21:32 +00007462 if (link_id != mld_assoc_link_id) {
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007463 sm->n_mld_affiliated_links++;
Sunil Ravi7f769292024-07-23 22:21:32 +00007464 ctx.addr = link->local_addr;
7465 ctx.mld_addr = NULL;
7466 ctx.link_id = -1;
7467 ctx.wpa_auth = NULL;
7468 wpa_auth_for_each_auth(sm->wpa_auth,
7469 wpa_get_link_sta_auth, &ctx);
7470 if (ctx.wpa_auth) {
7471 sm_link->wpa_auth = ctx.wpa_auth;
7472 wpa_group_get(sm_link->wpa_auth,
7473 sm_link->wpa_auth->group);
7474 }
7475 } else {
7476 sm_link->wpa_auth = sm->wpa_auth;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007477 }
7478
Sunil Ravi7f769292024-07-23 22:21:32 +00007479 if (!sm_link->wpa_auth)
7480 wpa_printf(MSG_ERROR,
7481 "Unable to find authenticator object for ML STA "
7482 MACSTR " on link id %d",
7483 MAC2STR(sm->wpa_auth->mld_addr),
7484 link_id);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00007485 }
7486#endif /* CONFIG_IEEE80211BE */
7487}