blob: 64a18009e1b5ab87318d42657d0138ec3e059c58 [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"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070026#include "crypto/random.h"
27#include "eapol_auth/eapol_auth_sm.h"
Hai Shalom74f70d42019-02-11 14:42:39 -080028#include "drivers/driver.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070029#include "ap_config.h"
30#include "ieee802_11.h"
31#include "wpa_auth.h"
32#include "pmksa_cache_auth.h"
33#include "wpa_auth_i.h"
34#include "wpa_auth_ie.h"
35
36#define STATE_MACHINE_DATA struct wpa_state_machine
37#define STATE_MACHINE_DEBUG_PREFIX "WPA"
38#define STATE_MACHINE_ADDR sm->addr
39
40
41static void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx);
42static int wpa_sm_step(struct wpa_state_machine *sm);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070043static int wpa_verify_key_mic(int akmp, size_t pmk_len, struct wpa_ptk *PTK,
44 u8 *data, size_t data_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -080045#ifdef CONFIG_FILS
46static int wpa_aead_decrypt(struct wpa_state_machine *sm, struct wpa_ptk *ptk,
47 u8 *buf, size_t buf_len, u16 *_key_data_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070048static struct wpabuf * fils_prepare_plainbuf(struct wpa_state_machine *sm,
49 const struct wpabuf *hlp);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -080050#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070051static void wpa_sm_call_step(void *eloop_ctx, void *timeout_ctx);
52static void wpa_group_sm_step(struct wpa_authenticator *wpa_auth,
53 struct wpa_group *group);
54static void wpa_request_new_ptk(struct wpa_state_machine *sm);
55static int wpa_gtk_update(struct wpa_authenticator *wpa_auth,
56 struct wpa_group *group);
57static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth,
58 struct wpa_group *group);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080059static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080060 const u8 *pmk, unsigned int pmk_len,
Hai Shalomfdcde762020-04-02 11:19:20 -070061 struct wpa_ptk *ptk, int force_sha256);
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070062static void wpa_group_free(struct wpa_authenticator *wpa_auth,
63 struct wpa_group *group);
64static void wpa_group_get(struct wpa_authenticator *wpa_auth,
65 struct wpa_group *group);
66static void wpa_group_put(struct wpa_authenticator *wpa_auth,
67 struct wpa_group *group);
Hai Shalomfdcde762020-04-02 11:19:20 -070068static int ieee80211w_kde_len(struct wpa_state_machine *sm);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -080069static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070070
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070071static const u32 eapol_key_timeout_first = 100; /* ms */
72static const u32 eapol_key_timeout_subseq = 1000; /* ms */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080073static const u32 eapol_key_timeout_first_group = 500; /* ms */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070074static const u32 eapol_key_timeout_no_retrans = 4000; /* ms */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070075
76/* TODO: make these configurable */
77static const int dot11RSNAConfigPMKLifetime = 43200;
78static const int dot11RSNAConfigPMKReauthThreshold = 70;
79static const int dot11RSNAConfigSATimeout = 60;
80
81
Dmitry Shmidtd5e49232012-12-03 15:08:10 -080082static inline int wpa_auth_mic_failure_report(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070083 struct wpa_authenticator *wpa_auth, const u8 *addr)
84{
Paul Stewart092955c2017-02-06 09:13:09 -080085 if (wpa_auth->cb->mic_failure_report)
86 return wpa_auth->cb->mic_failure_report(wpa_auth->cb_ctx, addr);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -080087 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070088}
89
90
Dmitry Shmidtdda10c22015-03-24 16:05:01 -070091static inline void wpa_auth_psk_failure_report(
92 struct wpa_authenticator *wpa_auth, const u8 *addr)
93{
Paul Stewart092955c2017-02-06 09:13:09 -080094 if (wpa_auth->cb->psk_failure_report)
95 wpa_auth->cb->psk_failure_report(wpa_auth->cb_ctx, addr);
Dmitry Shmidtdda10c22015-03-24 16:05:01 -070096}
97
98
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070099static inline void wpa_auth_set_eapol(struct wpa_authenticator *wpa_auth,
100 const u8 *addr, wpa_eapol_variable var,
101 int value)
102{
Paul Stewart092955c2017-02-06 09:13:09 -0800103 if (wpa_auth->cb->set_eapol)
104 wpa_auth->cb->set_eapol(wpa_auth->cb_ctx, addr, var, value);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700105}
106
107
108static inline int wpa_auth_get_eapol(struct wpa_authenticator *wpa_auth,
109 const u8 *addr, wpa_eapol_variable var)
110{
Hai Shalomfdcde762020-04-02 11:19:20 -0700111 if (!wpa_auth->cb->get_eapol)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700112 return -1;
Paul Stewart092955c2017-02-06 09:13:09 -0800113 return wpa_auth->cb->get_eapol(wpa_auth->cb_ctx, addr, var);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700114}
115
116
117static inline const u8 * wpa_auth_get_psk(struct wpa_authenticator *wpa_auth,
Dmitry Shmidt391c59f2013-09-03 12:16:28 -0700118 const u8 *addr,
119 const u8 *p2p_dev_addr,
Hai Shalom021b0b52019-04-10 11:17:58 -0700120 const u8 *prev_psk, size_t *psk_len,
121 int *vlan_id)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700122{
Hai Shalomfdcde762020-04-02 11:19:20 -0700123 if (!wpa_auth->cb->get_psk)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700124 return NULL;
Paul Stewart092955c2017-02-06 09:13:09 -0800125 return wpa_auth->cb->get_psk(wpa_auth->cb_ctx, addr, p2p_dev_addr,
Hai Shalom021b0b52019-04-10 11:17:58 -0700126 prev_psk, psk_len, vlan_id);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700127}
128
129
130static inline int wpa_auth_get_msk(struct wpa_authenticator *wpa_auth,
131 const u8 *addr, u8 *msk, size_t *len)
132{
Hai Shalomfdcde762020-04-02 11:19:20 -0700133 if (!wpa_auth->cb->get_msk)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700134 return -1;
Paul Stewart092955c2017-02-06 09:13:09 -0800135 return wpa_auth->cb->get_msk(wpa_auth->cb_ctx, addr, msk, len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700136}
137
138
139static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth,
140 int vlan_id,
141 enum wpa_alg alg, const u8 *addr, int idx,
Hai Shalomfdcde762020-04-02 11:19:20 -0700142 u8 *key, size_t key_len,
143 enum key_flag key_flag)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700144{
Hai Shalomfdcde762020-04-02 11:19:20 -0700145 if (!wpa_auth->cb->set_key)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700146 return -1;
Paul Stewart092955c2017-02-06 09:13:09 -0800147 return wpa_auth->cb->set_key(wpa_auth->cb_ctx, vlan_id, alg, addr, idx,
Hai Shalomfdcde762020-04-02 11:19:20 -0700148 key, key_len, key_flag);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700149}
150
151
Sunil Ravi89eba102022-09-13 21:04:37 -0700152#ifdef CONFIG_PASN
153static inline int wpa_auth_set_ltf_keyseed(struct wpa_authenticator *wpa_auth,
154 const u8 *peer_addr,
155 const u8 *ltf_keyseed,
156 size_t ltf_keyseed_len)
157{
158 if (!wpa_auth->cb->set_ltf_keyseed)
159 return -1;
160 return wpa_auth->cb->set_ltf_keyseed(wpa_auth->cb_ctx, peer_addr,
161 ltf_keyseed, ltf_keyseed_len);
162}
163#endif /* CONFIG_PASN */
164
165
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700166static inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth,
167 const u8 *addr, int idx, u8 *seq)
168{
Hai Shalomfdcde762020-04-02 11:19:20 -0700169 int res;
170
171 if (!wpa_auth->cb->get_seqnum)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700172 return -1;
Hai Shalomfdcde762020-04-02 11:19:20 -0700173 res = wpa_auth->cb->get_seqnum(wpa_auth->cb_ctx, addr, idx, seq);
174#ifdef CONFIG_TESTING_OPTIONS
175 if (!addr && idx < 4 && wpa_auth->conf.gtk_rsc_override_set) {
176 wpa_printf(MSG_DEBUG,
177 "TESTING: Override GTK RSC %016llx --> %016llx",
178 (long long unsigned) WPA_GET_LE64(seq),
179 (long long unsigned)
180 WPA_GET_LE64(wpa_auth->conf.gtk_rsc_override));
181 os_memcpy(seq, wpa_auth->conf.gtk_rsc_override,
182 WPA_KEY_RSC_LEN);
183 }
184 if (!addr && idx >= 4 && idx <= 5 &&
185 wpa_auth->conf.igtk_rsc_override_set) {
186 wpa_printf(MSG_DEBUG,
187 "TESTING: Override IGTK RSC %016llx --> %016llx",
188 (long long unsigned) WPA_GET_LE64(seq),
189 (long long unsigned)
190 WPA_GET_LE64(wpa_auth->conf.igtk_rsc_override));
191 os_memcpy(seq, wpa_auth->conf.igtk_rsc_override,
192 WPA_KEY_RSC_LEN);
193 }
194#endif /* CONFIG_TESTING_OPTIONS */
195 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700196}
197
198
199static inline int
200wpa_auth_send_eapol(struct wpa_authenticator *wpa_auth, const u8 *addr,
201 const u8 *data, size_t data_len, int encrypt)
202{
Hai Shalomfdcde762020-04-02 11:19:20 -0700203 if (!wpa_auth->cb->send_eapol)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700204 return -1;
Kai Shie75b0652020-11-24 20:31:29 -0800205#ifdef CONFIG_TESTING_OPTIONS
206 if (wpa_auth->conf.skip_send_eapol)
207 return 0;
208#endif
Paul Stewart092955c2017-02-06 09:13:09 -0800209 return wpa_auth->cb->send_eapol(wpa_auth->cb_ctx, addr, data, data_len,
210 encrypt);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700211}
212
213
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800214#ifdef CONFIG_MESH
215static inline int wpa_auth_start_ampe(struct wpa_authenticator *wpa_auth,
216 const u8 *addr)
217{
Hai Shalomfdcde762020-04-02 11:19:20 -0700218 if (!wpa_auth->cb->start_ampe)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800219 return -1;
Paul Stewart092955c2017-02-06 09:13:09 -0800220 return wpa_auth->cb->start_ampe(wpa_auth->cb_ctx, addr);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800221}
222#endif /* CONFIG_MESH */
223
224
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700225int wpa_auth_for_each_sta(struct wpa_authenticator *wpa_auth,
226 int (*cb)(struct wpa_state_machine *sm, void *ctx),
227 void *cb_ctx)
228{
Hai Shalomfdcde762020-04-02 11:19:20 -0700229 if (!wpa_auth->cb->for_each_sta)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700230 return 0;
Paul Stewart092955c2017-02-06 09:13:09 -0800231 return wpa_auth->cb->for_each_sta(wpa_auth->cb_ctx, cb, cb_ctx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700232}
233
234
235int wpa_auth_for_each_auth(struct wpa_authenticator *wpa_auth,
236 int (*cb)(struct wpa_authenticator *a, void *ctx),
237 void *cb_ctx)
238{
Hai Shalomfdcde762020-04-02 11:19:20 -0700239 if (!wpa_auth->cb->for_each_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700240 return 0;
Paul Stewart092955c2017-02-06 09:13:09 -0800241 return wpa_auth->cb->for_each_auth(wpa_auth->cb_ctx, cb, cb_ctx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700242}
243
244
Hai Shalom60840252021-02-19 19:02:11 -0800245void wpa_auth_store_ptksa(struct wpa_authenticator *wpa_auth,
246 const u8 *addr, int cipher,
247 u32 life_time, const struct wpa_ptk *ptk)
248{
249 if (wpa_auth->cb->store_ptksa)
250 wpa_auth->cb->store_ptksa(wpa_auth->cb_ctx, addr, cipher,
251 life_time, ptk);
252}
253
254
255void wpa_auth_remove_ptksa(struct wpa_authenticator *wpa_auth,
256 const u8 *addr, int cipher)
257{
258 if (wpa_auth->cb->clear_ptksa)
259 wpa_auth->cb->clear_ptksa(wpa_auth->cb_ctx, addr, cipher);
260}
261
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700262void wpa_auth_logger(struct wpa_authenticator *wpa_auth, const u8 *addr,
263 logger_level level, const char *txt)
264{
Hai Shalomfdcde762020-04-02 11:19:20 -0700265 if (!wpa_auth->cb->logger)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700266 return;
Paul Stewart092955c2017-02-06 09:13:09 -0800267 wpa_auth->cb->logger(wpa_auth->cb_ctx, addr, level, txt);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700268}
269
270
271void wpa_auth_vlogger(struct wpa_authenticator *wpa_auth, const u8 *addr,
272 logger_level level, const char *fmt, ...)
273{
274 char *format;
275 int maxlen;
276 va_list ap;
277
Hai Shalomfdcde762020-04-02 11:19:20 -0700278 if (!wpa_auth->cb->logger)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700279 return;
280
281 maxlen = os_strlen(fmt) + 100;
282 format = os_malloc(maxlen);
283 if (!format)
284 return;
285
286 va_start(ap, fmt);
287 vsnprintf(format, maxlen, fmt, ap);
288 va_end(ap);
289
290 wpa_auth_logger(wpa_auth, addr, level, format);
291
292 os_free(format);
293}
294
295
296static void wpa_sta_disconnect(struct wpa_authenticator *wpa_auth,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700297 const u8 *addr, u16 reason)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700298{
Hai Shalomfdcde762020-04-02 11:19:20 -0700299 if (!wpa_auth->cb->disconnect)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700300 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700301 wpa_printf(MSG_DEBUG, "wpa_sta_disconnect STA " MACSTR " (reason %u)",
302 MAC2STR(addr), reason);
303 wpa_auth->cb->disconnect(wpa_auth->cb_ctx, addr, reason);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700304}
305
306
Hai Shalom74f70d42019-02-11 14:42:39 -0800307#ifdef CONFIG_OCV
308static int wpa_channel_info(struct wpa_authenticator *wpa_auth,
309 struct wpa_channel_info *ci)
310{
311 if (!wpa_auth->cb->channel_info)
312 return -1;
313 return wpa_auth->cb->channel_info(wpa_auth->cb_ctx, ci);
314}
315#endif /* CONFIG_OCV */
316
317
Hai Shalom021b0b52019-04-10 11:17:58 -0700318static int wpa_auth_update_vlan(struct wpa_authenticator *wpa_auth,
319 const u8 *addr, int vlan_id)
320{
321 if (!wpa_auth->cb->update_vlan)
322 return -1;
323 return wpa_auth->cb->update_vlan(wpa_auth->cb_ctx, addr, vlan_id);
324}
325
326
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700327static void wpa_rekey_gmk(void *eloop_ctx, void *timeout_ctx)
328{
329 struct wpa_authenticator *wpa_auth = eloop_ctx;
330
331 if (random_get_bytes(wpa_auth->group->GMK, WPA_GMK_LEN)) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700332 wpa_printf(MSG_ERROR,
333 "Failed to get random data for WPA initialization.");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700334 } else {
335 wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "GMK rekeyd");
336 wpa_hexdump_key(MSG_DEBUG, "GMK",
337 wpa_auth->group->GMK, WPA_GMK_LEN);
338 }
339
340 if (wpa_auth->conf.wpa_gmk_rekey) {
341 eloop_register_timeout(wpa_auth->conf.wpa_gmk_rekey, 0,
342 wpa_rekey_gmk, wpa_auth, NULL);
343 }
344}
345
346
347static void wpa_rekey_gtk(void *eloop_ctx, void *timeout_ctx)
348{
349 struct wpa_authenticator *wpa_auth = eloop_ctx;
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700350 struct wpa_group *group, *next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700351
352 wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "rekeying GTK");
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700353 group = wpa_auth->group;
354 while (group) {
355 wpa_group_get(wpa_auth, group);
356
Hai Shalome21d4e82020-04-29 16:34:06 -0700357 group->GTKReKey = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700358 do {
Hai Shalome21d4e82020-04-29 16:34:06 -0700359 group->changed = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700360 wpa_group_sm_step(wpa_auth, group);
361 } while (group->changed);
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700362
363 next = group->next;
364 wpa_group_put(wpa_auth, group);
365 group = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700366 }
367
368 if (wpa_auth->conf.wpa_group_rekey) {
369 eloop_register_timeout(wpa_auth->conf.wpa_group_rekey,
370 0, wpa_rekey_gtk, wpa_auth, NULL);
371 }
372}
373
374
375static void wpa_rekey_ptk(void *eloop_ctx, void *timeout_ctx)
376{
377 struct wpa_authenticator *wpa_auth = eloop_ctx;
378 struct wpa_state_machine *sm = timeout_ctx;
379
380 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "rekeying PTK");
381 wpa_request_new_ptk(sm);
382 wpa_sm_step(sm);
383}
384
385
Hai Shalom81f62d82019-07-22 12:10:00 -0700386void wpa_auth_set_ptk_rekey_timer(struct wpa_state_machine *sm)
387{
388 if (sm && sm->wpa_auth->conf.wpa_ptk_rekey) {
389 wpa_printf(MSG_DEBUG, "WPA: Start PTK rekeying timer for "
390 MACSTR " (%d seconds)", MAC2STR(sm->addr),
391 sm->wpa_auth->conf.wpa_ptk_rekey);
392 eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm);
393 eloop_register_timeout(sm->wpa_auth->conf.wpa_ptk_rekey, 0,
394 wpa_rekey_ptk, sm->wpa_auth, sm);
395 }
396}
397
398
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700399static int wpa_auth_pmksa_clear_cb(struct wpa_state_machine *sm, void *ctx)
400{
401 if (sm->pmksa == ctx)
402 sm->pmksa = NULL;
403 return 0;
404}
405
406
407static void wpa_auth_pmksa_free_cb(struct rsn_pmksa_cache_entry *entry,
408 void *ctx)
409{
410 struct wpa_authenticator *wpa_auth = ctx;
411 wpa_auth_for_each_sta(wpa_auth, wpa_auth_pmksa_clear_cb, entry);
412}
413
414
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700415static int wpa_group_init_gmk_and_counter(struct wpa_authenticator *wpa_auth,
416 struct wpa_group *group)
417{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800418 u8 buf[ETH_ALEN + 8 + sizeof(unsigned long)];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700419 u8 rkey[32];
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800420 unsigned long ptr;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700421
422 if (random_get_bytes(group->GMK, WPA_GMK_LEN) < 0)
423 return -1;
424 wpa_hexdump_key(MSG_DEBUG, "GMK", group->GMK, WPA_GMK_LEN);
425
426 /*
427 * Counter = PRF-256(Random number, "Init Counter",
428 * Local MAC Address || Time)
429 */
430 os_memcpy(buf, wpa_auth->addr, ETH_ALEN);
431 wpa_get_ntp_timestamp(buf + ETH_ALEN);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800432 ptr = (unsigned long) group;
433 os_memcpy(buf + ETH_ALEN + 8, &ptr, sizeof(ptr));
Hai Shalom74f70d42019-02-11 14:42:39 -0800434#ifdef TEST_FUZZ
435 os_memset(buf + ETH_ALEN, 0xab, 8);
436 os_memset(buf + ETH_ALEN + 8, 0xcd, sizeof(ptr));
437#endif /* TEST_FUZZ */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700438 if (random_get_bytes(rkey, sizeof(rkey)) < 0)
439 return -1;
440
441 if (sha1_prf(rkey, sizeof(rkey), "Init Counter", buf, sizeof(buf),
442 group->Counter, WPA_NONCE_LEN) < 0)
443 return -1;
444 wpa_hexdump_key(MSG_DEBUG, "Key Counter",
445 group->Counter, WPA_NONCE_LEN);
446
447 return 0;
448}
449
450
451static struct wpa_group * wpa_group_init(struct wpa_authenticator *wpa_auth,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800452 int vlan_id, int delay_init)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700453{
454 struct wpa_group *group;
455
456 group = os_zalloc(sizeof(struct wpa_group));
Hai Shalomfdcde762020-04-02 11:19:20 -0700457 if (!group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700458 return NULL;
459
Hai Shalome21d4e82020-04-29 16:34:06 -0700460 group->GTKAuthenticator = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700461 group->vlan_id = vlan_id;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -0700462 group->GTK_len = wpa_cipher_key_len(wpa_auth->conf.wpa_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700463
464 if (random_pool_ready() != 1) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700465 wpa_printf(MSG_INFO,
466 "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 -0700467 }
468
469 /*
470 * Set initial GMK/Counter value here. The actual values that will be
471 * used in negotiations will be set once the first station tries to
472 * connect. This allows more time for collecting additional randomness
473 * on embedded devices.
474 */
475 if (wpa_group_init_gmk_and_counter(wpa_auth, group) < 0) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700476 wpa_printf(MSG_ERROR,
477 "Failed to get random data for WPA initialization.");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700478 os_free(group);
479 return NULL;
480 }
481
Hai Shalome21d4e82020-04-29 16:34:06 -0700482 group->GInit = true;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800483 if (delay_init) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700484 wpa_printf(MSG_DEBUG,
485 "WPA: Delay group state machine start until Beacon frames have been configured");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800486 /* Initialization is completed in wpa_init_keys(). */
487 } else {
488 wpa_group_sm_step(wpa_auth, group);
Hai Shalome21d4e82020-04-29 16:34:06 -0700489 group->GInit = false;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800490 wpa_group_sm_step(wpa_auth, group);
491 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700492
493 return group;
494}
495
496
497/**
498 * wpa_init - Initialize WPA authenticator
499 * @addr: Authenticator address
500 * @conf: Configuration for WPA authenticator
501 * @cb: Callback functions for WPA authenticator
502 * Returns: Pointer to WPA authenticator data or %NULL on failure
503 */
504struct wpa_authenticator * wpa_init(const u8 *addr,
505 struct wpa_auth_config *conf,
Paul Stewart092955c2017-02-06 09:13:09 -0800506 const struct wpa_auth_callbacks *cb,
507 void *cb_ctx)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700508{
509 struct wpa_authenticator *wpa_auth;
510
511 wpa_auth = os_zalloc(sizeof(struct wpa_authenticator));
Hai Shalomfdcde762020-04-02 11:19:20 -0700512 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700513 return NULL;
514 os_memcpy(wpa_auth->addr, addr, ETH_ALEN);
515 os_memcpy(&wpa_auth->conf, conf, sizeof(*conf));
Paul Stewart092955c2017-02-06 09:13:09 -0800516 wpa_auth->cb = cb;
517 wpa_auth->cb_ctx = cb_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700518
519 if (wpa_auth_gen_wpa_ie(wpa_auth)) {
520 wpa_printf(MSG_ERROR, "Could not generate WPA IE.");
521 os_free(wpa_auth);
522 return NULL;
523 }
524
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800525 wpa_auth->group = wpa_group_init(wpa_auth, 0, 1);
Hai Shalomfdcde762020-04-02 11:19:20 -0700526 if (!wpa_auth->group) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700527 os_free(wpa_auth->wpa_ie);
528 os_free(wpa_auth);
529 return NULL;
530 }
531
532 wpa_auth->pmksa = pmksa_cache_auth_init(wpa_auth_pmksa_free_cb,
533 wpa_auth);
Hai Shalomfdcde762020-04-02 11:19:20 -0700534 if (!wpa_auth->pmksa) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700535 wpa_printf(MSG_ERROR, "PMKSA cache initialization failed.");
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800536 os_free(wpa_auth->group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700537 os_free(wpa_auth->wpa_ie);
538 os_free(wpa_auth);
539 return NULL;
540 }
541
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800542#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700543 wpa_auth->ft_pmk_cache = wpa_ft_pmk_cache_init();
Hai Shalomfdcde762020-04-02 11:19:20 -0700544 if (!wpa_auth->ft_pmk_cache) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700545 wpa_printf(MSG_ERROR, "FT PMK cache initialization failed.");
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800546 os_free(wpa_auth->group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700547 os_free(wpa_auth->wpa_ie);
548 pmksa_cache_auth_deinit(wpa_auth->pmksa);
549 os_free(wpa_auth);
550 return NULL;
551 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800552#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700553
554 if (wpa_auth->conf.wpa_gmk_rekey) {
555 eloop_register_timeout(wpa_auth->conf.wpa_gmk_rekey, 0,
556 wpa_rekey_gmk, wpa_auth, NULL);
557 }
558
559 if (wpa_auth->conf.wpa_group_rekey) {
560 eloop_register_timeout(wpa_auth->conf.wpa_group_rekey, 0,
561 wpa_rekey_gtk, wpa_auth, NULL);
562 }
563
Dmitry Shmidtcf32e602014-01-28 10:57:39 -0800564#ifdef CONFIG_P2P
565 if (WPA_GET_BE32(conf->ip_addr_start)) {
566 int count = WPA_GET_BE32(conf->ip_addr_end) -
567 WPA_GET_BE32(conf->ip_addr_start) + 1;
568 if (count > 1000)
569 count = 1000;
570 if (count > 0)
571 wpa_auth->ip_pool = bitfield_alloc(count);
572 }
573#endif /* CONFIG_P2P */
574
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700575 return wpa_auth;
576}
577
578
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800579int wpa_init_keys(struct wpa_authenticator *wpa_auth)
580{
581 struct wpa_group *group = wpa_auth->group;
582
Hai Shalomfdcde762020-04-02 11:19:20 -0700583 wpa_printf(MSG_DEBUG,
584 "WPA: Start group state machine to set initial keys");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800585 wpa_group_sm_step(wpa_auth, group);
Hai Shalome21d4e82020-04-29 16:34:06 -0700586 group->GInit = false;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800587 wpa_group_sm_step(wpa_auth, group);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800588 if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
589 return -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800590 return 0;
591}
592
593
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700594/**
595 * wpa_deinit - Deinitialize WPA authenticator
596 * @wpa_auth: Pointer to WPA authenticator data from wpa_init()
597 */
598void wpa_deinit(struct wpa_authenticator *wpa_auth)
599{
600 struct wpa_group *group, *prev;
601
602 eloop_cancel_timeout(wpa_rekey_gmk, wpa_auth, NULL);
603 eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL);
604
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700605 pmksa_cache_auth_deinit(wpa_auth->pmksa);
606
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800607#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700608 wpa_ft_pmk_cache_deinit(wpa_auth->ft_pmk_cache);
609 wpa_auth->ft_pmk_cache = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700610 wpa_ft_deinit(wpa_auth);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800611#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700612
Dmitry Shmidtcf32e602014-01-28 10:57:39 -0800613#ifdef CONFIG_P2P
614 bitfield_free(wpa_auth->ip_pool);
615#endif /* CONFIG_P2P */
616
617
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700618 os_free(wpa_auth->wpa_ie);
619
620 group = wpa_auth->group;
621 while (group) {
622 prev = group;
623 group = group->next;
Sunil Ravia04bd252022-05-02 22:54:18 -0700624 bin_clear_free(prev, sizeof(*prev));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700625 }
626
627 os_free(wpa_auth);
628}
629
630
631/**
632 * wpa_reconfig - Update WPA authenticator configuration
633 * @wpa_auth: Pointer to WPA authenticator data from wpa_init()
634 * @conf: Configuration for WPA authenticator
635 */
636int wpa_reconfig(struct wpa_authenticator *wpa_auth,
637 struct wpa_auth_config *conf)
638{
639 struct wpa_group *group;
Hai Shalomfdcde762020-04-02 11:19:20 -0700640
641 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700642 return 0;
643
644 os_memcpy(&wpa_auth->conf, conf, sizeof(*conf));
645 if (wpa_auth_gen_wpa_ie(wpa_auth)) {
646 wpa_printf(MSG_ERROR, "Could not generate WPA IE.");
647 return -1;
648 }
649
650 /*
651 * Reinitialize GTK to make sure it is suitable for the new
652 * configuration.
653 */
654 group = wpa_auth->group;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -0700655 group->GTK_len = wpa_cipher_key_len(wpa_auth->conf.wpa_group);
Hai Shalome21d4e82020-04-29 16:34:06 -0700656 group->GInit = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700657 wpa_group_sm_step(wpa_auth, group);
Hai Shalome21d4e82020-04-29 16:34:06 -0700658 group->GInit = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700659 wpa_group_sm_step(wpa_auth, group);
660
661 return 0;
662}
663
664
665struct wpa_state_machine *
Dmitry Shmidt391c59f2013-09-03 12:16:28 -0700666wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr,
667 const u8 *p2p_dev_addr)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700668{
669 struct wpa_state_machine *sm;
670
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800671 if (wpa_auth->group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
672 return NULL;
673
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700674 sm = os_zalloc(sizeof(struct wpa_state_machine));
Hai Shalomfdcde762020-04-02 11:19:20 -0700675 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700676 return NULL;
677 os_memcpy(sm->addr, addr, ETH_ALEN);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -0700678 if (p2p_dev_addr)
679 os_memcpy(sm->p2p_dev_addr, p2p_dev_addr, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700680
681 sm->wpa_auth = wpa_auth;
682 sm->group = wpa_auth->group;
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700683 wpa_group_get(sm->wpa_auth, sm->group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700684
685 return sm;
686}
687
688
689int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth,
690 struct wpa_state_machine *sm)
691{
Hai Shalomfdcde762020-04-02 11:19:20 -0700692 if (!wpa_auth || !wpa_auth->conf.wpa || !sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700693 return -1;
694
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800695#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700696 if (sm->ft_completed) {
697 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -0700698 "FT authentication already completed - do not start 4-way handshake");
Dmitry Shmidt71757432014-06-02 13:50:35 -0700699 /* Go to PTKINITDONE state to allow GTK rekeying */
700 sm->wpa_ptk_state = WPA_PTK_PTKINITDONE;
Hai Shalome21d4e82020-04-29 16:34:06 -0700701 sm->Pair = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700702 return 0;
703 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800704#endif /* CONFIG_IEEE80211R_AP */
705
706#ifdef CONFIG_FILS
707 if (sm->fils_completed) {
708 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
709 "FILS authentication already completed - do not start 4-way handshake");
710 /* Go to PTKINITDONE state to allow GTK rekeying */
711 sm->wpa_ptk_state = WPA_PTK_PTKINITDONE;
Hai Shalome21d4e82020-04-29 16:34:06 -0700712 sm->Pair = true;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800713 return 0;
714 }
715#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700716
717 if (sm->started) {
718 os_memset(&sm->key_replay, 0, sizeof(sm->key_replay));
Hai Shalome21d4e82020-04-29 16:34:06 -0700719 sm->ReAuthenticationRequest = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700720 return wpa_sm_step(sm);
721 }
722
723 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
724 "start authentication");
725 sm->started = 1;
726
Hai Shalome21d4e82020-04-29 16:34:06 -0700727 sm->Init = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700728 if (wpa_sm_step(sm) == 1)
729 return 1; /* should not really happen */
Hai Shalome21d4e82020-04-29 16:34:06 -0700730 sm->Init = false;
731 sm->AuthenticationRequest = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700732 return wpa_sm_step(sm);
733}
734
735
736void wpa_auth_sta_no_wpa(struct wpa_state_machine *sm)
737{
738 /* WPA/RSN was not used - clear WPA state. This is needed if the STA
739 * reassociates back to the same AP while the previous entry for the
740 * STA has not yet been removed. */
Hai Shalomfdcde762020-04-02 11:19:20 -0700741 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700742 return;
743
744 sm->wpa_key_mgmt = 0;
745}
746
747
748static void wpa_free_sta_sm(struct wpa_state_machine *sm)
749{
Dmitry Shmidtcf32e602014-01-28 10:57:39 -0800750#ifdef CONFIG_P2P
751 if (WPA_GET_BE32(sm->ip_addr)) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700752 wpa_printf(MSG_DEBUG,
753 "P2P: Free assigned IP address %u.%u.%u.%u from "
Sunil8cd6f4d2022-06-28 18:40:46 +0000754 MACSTR " (bit %u)",
Dmitry Shmidtcf32e602014-01-28 10:57:39 -0800755 sm->ip_addr[0], sm->ip_addr[1],
756 sm->ip_addr[2], sm->ip_addr[3],
Sunil8cd6f4d2022-06-28 18:40:46 +0000757 MAC2STR(sm->addr), sm->ip_addr_bit);
758 bitfield_clear(sm->wpa_auth->ip_pool, sm->ip_addr_bit);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -0800759 }
760#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700761 if (sm->GUpdateStationKeys) {
762 sm->group->GKeyDoneStations--;
Hai Shalome21d4e82020-04-29 16:34:06 -0700763 sm->GUpdateStationKeys = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700764 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800765#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700766 os_free(sm->assoc_resp_ftie);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700767 wpabuf_free(sm->ft_pending_req_ies);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800768#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700769 os_free(sm->last_rx_eapol_key);
770 os_free(sm->wpa_ie);
Hai Shalomc3565922019-10-28 11:58:20 -0700771 os_free(sm->rsnxe);
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700772 wpa_group_put(sm->wpa_auth, sm->group);
Hai Shalom021b0b52019-04-10 11:17:58 -0700773#ifdef CONFIG_DPP2
774 wpabuf_clear_free(sm->dpp_z);
775#endif /* CONFIG_DPP2 */
Hai Shalom1dc4d202019-04-29 16:22:27 -0700776 bin_clear_free(sm, sizeof(*sm));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700777}
778
779
780void wpa_auth_sta_deinit(struct wpa_state_machine *sm)
781{
Hai Shalomfdcde762020-04-02 11:19:20 -0700782 struct wpa_authenticator *wpa_auth;
783
784 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700785 return;
786
Hai Shalomfdcde762020-04-02 11:19:20 -0700787 wpa_auth = sm->wpa_auth;
788 if (wpa_auth->conf.wpa_strict_rekey && sm->has_GTK) {
789 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
790 "strict rekeying - force GTK rekey since STA is leaving");
Roshan Pius3a1667e2018-07-03 15:17:14 -0700791 if (eloop_deplete_timeout(0, 500000, wpa_rekey_gtk,
Hai Shalomfdcde762020-04-02 11:19:20 -0700792 wpa_auth, NULL) == -1)
793 eloop_register_timeout(0, 500000, wpa_rekey_gtk,
794 wpa_auth, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700795 }
796
Hai Shalomfdcde762020-04-02 11:19:20 -0700797 eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700798 sm->pending_1_of_4_timeout = 0;
799 eloop_cancel_timeout(wpa_sm_call_step, sm, NULL);
Hai Shalomfdcde762020-04-02 11:19:20 -0700800 eloop_cancel_timeout(wpa_rekey_ptk, wpa_auth, sm);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700801#ifdef CONFIG_IEEE80211R_AP
802 wpa_ft_sta_deinit(sm);
803#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700804 if (sm->in_step_loop) {
805 /* Must not free state machine while wpa_sm_step() is running.
806 * Freeing will be completed in the end of wpa_sm_step(). */
Hai Shalomfdcde762020-04-02 11:19:20 -0700807 wpa_printf(MSG_DEBUG,
808 "WPA: Registering pending STA state machine deinit for "
809 MACSTR, MAC2STR(sm->addr));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700810 sm->pending_deinit = 1;
811 } else
812 wpa_free_sta_sm(sm);
813}
814
815
816static void wpa_request_new_ptk(struct wpa_state_machine *sm)
817{
Hai Shalomfdcde762020-04-02 11:19:20 -0700818 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700819 return;
820
Hai Shalomfdcde762020-04-02 11:19:20 -0700821 if (!sm->use_ext_key_id && sm->wpa_auth->conf.wpa_deny_ptk0_rekey) {
822 wpa_printf(MSG_INFO,
823 "WPA: PTK0 rekey not allowed, disconnect " MACSTR,
824 MAC2STR(sm->addr));
Hai Shalome21d4e82020-04-29 16:34:06 -0700825 sm->Disconnect = true;
Hai Shalomfdcde762020-04-02 11:19:20 -0700826 /* Try to encourage the STA to reconnect */
827 sm->disconnect_reason =
828 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA;
829 } else {
830 if (sm->use_ext_key_id)
831 sm->keyidx_active ^= 1; /* flip Key ID */
Hai Shalome21d4e82020-04-29 16:34:06 -0700832 sm->PTKRequest = true;
Hai Shalomfdcde762020-04-02 11:19:20 -0700833 sm->PTK_valid = 0;
834 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700835}
836
837
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800838static int wpa_replay_counter_valid(struct wpa_key_replay_counter *ctr,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700839 const u8 *replay_counter)
840{
841 int i;
842 for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800843 if (!ctr[i].valid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700844 break;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800845 if (os_memcmp(replay_counter, ctr[i].counter,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700846 WPA_REPLAY_COUNTER_LEN) == 0)
847 return 1;
848 }
849 return 0;
850}
851
852
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800853static void wpa_replay_counter_mark_invalid(struct wpa_key_replay_counter *ctr,
854 const u8 *replay_counter)
855{
856 int i;
857 for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) {
858 if (ctr[i].valid &&
Hai Shalomfdcde762020-04-02 11:19:20 -0700859 (!replay_counter ||
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800860 os_memcmp(replay_counter, ctr[i].counter,
861 WPA_REPLAY_COUNTER_LEN) == 0))
Hai Shalome21d4e82020-04-29 16:34:06 -0700862 ctr[i].valid = false;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800863 }
864}
865
866
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800867#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700868static int ft_check_msg_2_of_4(struct wpa_authenticator *wpa_auth,
869 struct wpa_state_machine *sm,
870 struct wpa_eapol_ie_parse *kde)
871{
872 struct wpa_ie_data ie;
873 struct rsn_mdie *mdie;
874
875 if (wpa_parse_wpa_ie_rsn(kde->rsn_ie, kde->rsn_ie_len, &ie) < 0 ||
Hai Shalomfdcde762020-04-02 11:19:20 -0700876 ie.num_pmkid != 1 || !ie.pmkid) {
877 wpa_printf(MSG_DEBUG,
878 "FT: No PMKR1Name in FT 4-way handshake message 2/4");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700879 return -1;
880 }
881
882 os_memcpy(sm->sup_pmk_r1_name, ie.pmkid, PMKID_LEN);
883 wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from Supplicant",
884 sm->sup_pmk_r1_name, PMKID_LEN);
885
886 if (!kde->mdie || !kde->ftie) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700887 wpa_printf(MSG_DEBUG,
888 "FT: No %s in FT 4-way handshake message 2/4",
889 kde->mdie ? "FTIE" : "MDIE");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700890 return -1;
891 }
892
893 mdie = (struct rsn_mdie *) (kde->mdie + 2);
894 if (kde->mdie[1] < sizeof(struct rsn_mdie) ||
895 os_memcmp(wpa_auth->conf.mobility_domain, mdie->mobility_domain,
896 MOBILITY_DOMAIN_ID_LEN) != 0) {
897 wpa_printf(MSG_DEBUG, "FT: MDIE mismatch");
898 return -1;
899 }
900
901 if (sm->assoc_resp_ftie &&
902 (kde->ftie[1] != sm->assoc_resp_ftie[1] ||
903 os_memcmp(kde->ftie, sm->assoc_resp_ftie,
904 2 + sm->assoc_resp_ftie[1]) != 0)) {
905 wpa_printf(MSG_DEBUG, "FT: FTIE mismatch");
906 wpa_hexdump(MSG_DEBUG, "FT: FTIE in EAPOL-Key msg 2/4",
907 kde->ftie, kde->ftie_len);
908 wpa_hexdump(MSG_DEBUG, "FT: FTIE in (Re)AssocResp",
909 sm->assoc_resp_ftie, 2 + sm->assoc_resp_ftie[1]);
910 return -1;
911 }
912
913 return 0;
914}
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800915#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700916
917
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800918static int wpa_receive_error_report(struct wpa_authenticator *wpa_auth,
919 struct wpa_state_machine *sm, int group)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800920{
921 /* Supplicant reported a Michael MIC error */
922 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -0700923 "received EAPOL-Key Error Request (STA detected Michael MIC failure (group=%d))",
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800924 group);
925
926 if (group && wpa_auth->conf.wpa_group != WPA_CIPHER_TKIP) {
927 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -0700928 "ignore Michael MIC failure report since group cipher is not TKIP");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800929 } else if (!group && sm->pairwise != WPA_CIPHER_TKIP) {
930 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -0700931 "ignore Michael MIC failure report since pairwise cipher is not TKIP");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800932 } else {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800933 if (wpa_auth_mic_failure_report(wpa_auth, sm->addr) > 0)
934 return 1; /* STA entry was removed */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800935 sm->dot11RSNAStatsTKIPRemoteMICFailures++;
936 wpa_auth->dot11RSNAStatsTKIPRemoteMICFailures++;
937 }
938
939 /*
940 * Error report is not a request for a new key handshake, but since
941 * Authenticator may do it, let's change the keys now anyway.
942 */
943 wpa_request_new_ptk(sm);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800944 return 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800945}
946
947
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800948static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data,
949 size_t data_len)
950{
951 struct wpa_ptk PTK;
952 int ok = 0;
953 const u8 *pmk = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700954 size_t pmk_len;
Hai Shalom021b0b52019-04-10 11:17:58 -0700955 int vlan_id = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800956
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800957 os_memset(&PTK, 0, sizeof(PTK));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800958 for (;;) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700959 if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
960 !wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800961 pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr,
Hai Shalom021b0b52019-04-10 11:17:58 -0700962 sm->p2p_dev_addr, pmk, &pmk_len,
963 &vlan_id);
Hai Shalomfdcde762020-04-02 11:19:20 -0700964 if (!pmk)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800965 break;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700966#ifdef CONFIG_IEEE80211R_AP
967 if (wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) {
968 os_memcpy(sm->xxkey, pmk, pmk_len);
969 sm->xxkey_len = pmk_len;
970 }
971#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800972 } else {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800973 pmk = sm->PMK;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800974 pmk_len = sm->pmk_len;
975 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800976
Hai Shalomfdcde762020-04-02 11:19:20 -0700977 if (wpa_derive_ptk(sm, sm->alt_SNonce, pmk, pmk_len, &PTK, 0) <
978 0)
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800979 break;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800980
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700981 if (wpa_verify_key_mic(sm->wpa_key_mgmt, pmk_len, &PTK,
982 data, data_len) == 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -0700983 if (sm->PMK != pmk) {
984 os_memcpy(sm->PMK, pmk, pmk_len);
985 sm->pmk_len = pmk_len;
986 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800987 ok = 1;
988 break;
989 }
990
Roshan Pius3a1667e2018-07-03 15:17:14 -0700991 if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
992 wpa_key_mgmt_sae(sm->wpa_key_mgmt))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800993 break;
994 }
995
996 if (!ok) {
997 wpa_printf(MSG_DEBUG,
998 "WPA: Earlier SNonce did not result in matching MIC");
999 return -1;
1000 }
1001
1002 wpa_printf(MSG_DEBUG,
1003 "WPA: Earlier SNonce resulted in matching MIC");
1004 sm->alt_snonce_valid = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -07001005
1006 if (vlan_id && wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
1007 wpa_auth_update_vlan(sm->wpa_auth, sm->addr, vlan_id) < 0)
1008 return -1;
1009
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001010 os_memcpy(sm->SNonce, sm->alt_SNonce, WPA_NONCE_LEN);
1011 os_memcpy(&sm->PTK, &PTK, sizeof(PTK));
Hai Shalom81f62d82019-07-22 12:10:00 -07001012 forced_memzero(&PTK, sizeof(PTK));
Hai Shalome21d4e82020-04-29 16:34:06 -07001013 sm->PTK_valid = true;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001014
1015 return 0;
1016}
1017
1018
Hai Shaloma20dcd72022-02-04 13:43:00 -08001019static bool wpa_auth_gtk_rekey_in_process(struct wpa_authenticator *wpa_auth)
1020{
1021 struct wpa_group *group;
1022
1023 for (group = wpa_auth->group; group; group = group->next) {
1024 if (group->GKeyDoneStations)
1025 return true;
1026 }
1027 return false;
1028}
1029
1030
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001031void wpa_receive(struct wpa_authenticator *wpa_auth,
1032 struct wpa_state_machine *sm,
1033 u8 *data, size_t data_len)
1034{
1035 struct ieee802_1x_hdr *hdr;
1036 struct wpa_eapol_key *key;
1037 u16 key_info, key_data_length;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001038 enum { PAIRWISE_2, PAIRWISE_4, GROUP_2, REQUEST } msg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001039 char *msgtxt;
1040 struct wpa_eapol_ie_parse kde;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001041 const u8 *key_data;
1042 size_t keyhdrlen, mic_len;
1043 u8 *mic;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001044
Hai Shalomfdcde762020-04-02 11:19:20 -07001045 if (!wpa_auth || !wpa_auth->conf.wpa || !sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001046 return;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001047 wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL data", data, data_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001048
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001049 mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001050 keyhdrlen = sizeof(*key) + mic_len + 2;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001051
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001052 if (data_len < sizeof(*hdr) + keyhdrlen) {
1053 wpa_printf(MSG_DEBUG, "WPA: Ignore too short EAPOL-Key frame");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001054 return;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001055 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001056
1057 hdr = (struct ieee802_1x_hdr *) data;
1058 key = (struct wpa_eapol_key *) (hdr + 1);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001059 mic = (u8 *) (key + 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001060 key_info = WPA_GET_BE16(key->key_info);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001061 key_data = mic + mic_len + 2;
1062 key_data_length = WPA_GET_BE16(mic + mic_len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001063 wpa_printf(MSG_DEBUG, "WPA: Received EAPOL-Key from " MACSTR
Hai Shalomfdcde762020-04-02 11:19:20 -07001064 " key_info=0x%x type=%u mic_len=%zu key_data_length=%u",
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001065 MAC2STR(sm->addr), key_info, key->type,
Hai Shalomfdcde762020-04-02 11:19:20 -07001066 mic_len, key_data_length);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001067 wpa_hexdump(MSG_MSGDUMP,
1068 "WPA: EAPOL-Key header (ending before Key MIC)",
1069 key, sizeof(*key));
1070 wpa_hexdump(MSG_MSGDUMP, "WPA: EAPOL-Key Key MIC",
1071 mic, mic_len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001072 if (key_data_length > data_len - sizeof(*hdr) - keyhdrlen) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001073 wpa_printf(MSG_INFO,
1074 "WPA: Invalid EAPOL-Key frame - key_data overflow (%d > %zu)",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001075 key_data_length,
Hai Shalomfdcde762020-04-02 11:19:20 -07001076 data_len - sizeof(*hdr) - keyhdrlen);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001077 return;
1078 }
1079
1080 if (sm->wpa == WPA_VERSION_WPA2) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001081 if (key->type == EAPOL_KEY_TYPE_WPA) {
1082 /*
1083 * Some deployed station implementations seem to send
1084 * msg 4/4 with incorrect type value in WPA2 mode.
1085 */
Hai Shalomfdcde762020-04-02 11:19:20 -07001086 wpa_printf(MSG_DEBUG,
1087 "Workaround: Allow EAPOL-Key with unexpected WPA type in RSN mode");
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001088 } else if (key->type != EAPOL_KEY_TYPE_RSN) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001089 wpa_printf(MSG_DEBUG,
1090 "Ignore EAPOL-Key with unexpected type %d in RSN mode",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001091 key->type);
1092 return;
1093 }
1094 } else {
1095 if (key->type != EAPOL_KEY_TYPE_WPA) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001096 wpa_printf(MSG_DEBUG,
1097 "Ignore EAPOL-Key with unexpected type %d in WPA mode",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001098 key->type);
1099 return;
1100 }
1101 }
1102
1103 wpa_hexdump(MSG_DEBUG, "WPA: Received Key Nonce", key->key_nonce,
1104 WPA_NONCE_LEN);
1105 wpa_hexdump(MSG_DEBUG, "WPA: Received Replay Counter",
1106 key->replay_counter, WPA_REPLAY_COUNTER_LEN);
1107
1108 /* FIX: verify that the EAPOL-Key frame was encrypted if pairwise keys
1109 * are set */
1110
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001111 if (key_info & WPA_KEY_INFO_SMK_MESSAGE) {
1112 wpa_printf(MSG_DEBUG, "WPA: Ignore SMK message");
1113 return;
1114 }
1115
1116 if (key_info & WPA_KEY_INFO_REQUEST) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001117 msg = REQUEST;
1118 msgtxt = "Request";
1119 } else if (!(key_info & WPA_KEY_INFO_KEY_TYPE)) {
1120 msg = GROUP_2;
1121 msgtxt = "2/2 Group";
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001122 } else if (key_data_length == 0 ||
1123 (mic_len == 0 && (key_info & WPA_KEY_INFO_ENCR_KEY_DATA) &&
1124 key_data_length == AES_BLOCK_SIZE)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001125 msg = PAIRWISE_4;
1126 msgtxt = "4/4 Pairwise";
1127 } else {
1128 msg = PAIRWISE_2;
1129 msgtxt = "2/4 Pairwise";
1130 }
1131
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001132 if (msg == REQUEST || msg == PAIRWISE_2 || msg == PAIRWISE_4 ||
1133 msg == GROUP_2) {
1134 u16 ver = key_info & WPA_KEY_INFO_TYPE_MASK;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001135 if (sm->pairwise == WPA_CIPHER_CCMP ||
1136 sm->pairwise == WPA_CIPHER_GCMP) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001137 if (wpa_use_cmac(sm->wpa_key_mgmt) &&
1138 !wpa_use_akm_defined(sm->wpa_key_mgmt) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001139 ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) {
1140 wpa_auth_logger(wpa_auth, sm->addr,
1141 LOGGER_WARNING,
Hai Shalomfdcde762020-04-02 11:19:20 -07001142 "advertised support for AES-128-CMAC, but did not use it");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001143 return;
1144 }
1145
Roshan Pius3a1667e2018-07-03 15:17:14 -07001146 if (!wpa_use_cmac(sm->wpa_key_mgmt) &&
1147 !wpa_use_akm_defined(sm->wpa_key_mgmt) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001148 ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
1149 wpa_auth_logger(wpa_auth, sm->addr,
1150 LOGGER_WARNING,
Hai Shalomfdcde762020-04-02 11:19:20 -07001151 "did not use HMAC-SHA1-AES with CCMP/GCMP");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001152 return;
1153 }
1154 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001155
Roshan Pius3a1667e2018-07-03 15:17:14 -07001156 if (wpa_use_akm_defined(sm->wpa_key_mgmt) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001157 ver != WPA_KEY_INFO_TYPE_AKM_DEFINED) {
1158 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING,
1159 "did not use EAPOL-Key descriptor version 0 as required for AKM-defined cases");
1160 return;
1161 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001162 }
1163
1164 if (key_info & WPA_KEY_INFO_REQUEST) {
1165 if (sm->req_replay_counter_used &&
1166 os_memcmp(key->replay_counter, sm->req_replay_counter,
1167 WPA_REPLAY_COUNTER_LEN) <= 0) {
1168 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING,
Hai Shalomfdcde762020-04-02 11:19:20 -07001169 "received EAPOL-Key request with replayed counter");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001170 return;
1171 }
1172 }
1173
1174 if (!(key_info & WPA_KEY_INFO_REQUEST) &&
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001175 !wpa_replay_counter_valid(sm->key_replay, key->replay_counter)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001176 int i;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001177
1178 if (msg == PAIRWISE_2 &&
1179 wpa_replay_counter_valid(sm->prev_key_replay,
1180 key->replay_counter) &&
1181 sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING &&
1182 os_memcmp(sm->SNonce, key->key_nonce, WPA_NONCE_LEN) != 0)
1183 {
1184 /*
1185 * Some supplicant implementations (e.g., Windows XP
1186 * WZC) update SNonce for each EAPOL-Key 2/4. This
1187 * breaks the workaround on accepting any of the
1188 * pending requests, so allow the SNonce to be updated
1189 * even if we have already sent out EAPOL-Key 3/4.
1190 */
1191 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07001192 "Process SNonce update from STA based on retransmitted EAPOL-Key 1/4");
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001193 sm->update_snonce = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001194 os_memcpy(sm->alt_SNonce, sm->SNonce, WPA_NONCE_LEN);
Hai Shalome21d4e82020-04-29 16:34:06 -07001195 sm->alt_snonce_valid = true;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001196 os_memcpy(sm->alt_replay_counter,
1197 sm->key_replay[0].counter,
1198 WPA_REPLAY_COUNTER_LEN);
1199 goto continue_processing;
1200 }
1201
1202 if (msg == PAIRWISE_4 && sm->alt_snonce_valid &&
1203 sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING &&
1204 os_memcmp(key->replay_counter, sm->alt_replay_counter,
1205 WPA_REPLAY_COUNTER_LEN) == 0) {
1206 /*
1207 * Supplicant may still be using the old SNonce since
1208 * there was two EAPOL-Key 2/4 messages and they had
1209 * different SNonce values.
1210 */
1211 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
1212 "Try to process received EAPOL-Key 4/4 based on old Replay Counter and SNonce from an earlier EAPOL-Key 1/4");
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001213 goto continue_processing;
1214 }
1215
1216 if (msg == PAIRWISE_2 &&
1217 wpa_replay_counter_valid(sm->prev_key_replay,
1218 key->replay_counter) &&
1219 sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING) {
1220 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07001221 "ignore retransmitted EAPOL-Key %s - SNonce did not change",
1222 msgtxt);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001223 } else {
1224 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07001225 "received EAPOL-Key %s with unexpected replay counter",
1226 msgtxt);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001227 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001228 for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) {
1229 if (!sm->key_replay[i].valid)
1230 break;
1231 wpa_hexdump(MSG_DEBUG, "pending replay counter",
1232 sm->key_replay[i].counter,
1233 WPA_REPLAY_COUNTER_LEN);
1234 }
1235 wpa_hexdump(MSG_DEBUG, "received replay counter",
1236 key->replay_counter, WPA_REPLAY_COUNTER_LEN);
1237 return;
1238 }
1239
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001240continue_processing:
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001241#ifdef CONFIG_FILS
1242 if (sm->wpa == WPA_VERSION_WPA2 && mic_len == 0 &&
1243 !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
1244 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
1245 "WPA: Encr Key Data bit not set even though AEAD cipher is supposed to be used - drop frame");
1246 return;
1247 }
1248#endif /* CONFIG_FILS */
1249
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001250 switch (msg) {
1251 case PAIRWISE_2:
1252 if (sm->wpa_ptk_state != WPA_PTK_PTKSTART &&
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001253 sm->wpa_ptk_state != WPA_PTK_PTKCALCNEGOTIATING &&
1254 (!sm->update_snonce ||
1255 sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001256 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001257 "received EAPOL-Key msg 2/4 in invalid state (%d) - dropped",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001258 sm->wpa_ptk_state);
1259 return;
1260 }
1261 random_add_randomness(key->key_nonce, WPA_NONCE_LEN);
1262 if (sm->group->reject_4way_hs_for_entropy) {
1263 /*
1264 * The system did not have enough entropy to generate
1265 * strong random numbers. Reject the first 4-way
1266 * handshake(s) and collect some entropy based on the
1267 * information from it. Once enough entropy is
1268 * available, the next atempt will trigger GMK/Key
1269 * Counter update and the station will be allowed to
1270 * continue.
1271 */
Hai Shalomfdcde762020-04-02 11:19:20 -07001272 wpa_printf(MSG_DEBUG,
1273 "WPA: Reject 4-way handshake to collect more entropy for random number generation");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001274 random_mark_pool_ready();
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001275 wpa_sta_disconnect(wpa_auth, sm->addr,
1276 WLAN_REASON_PREV_AUTH_NOT_VALID);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001277 return;
1278 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001279 break;
1280 case PAIRWISE_4:
1281 if (sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING ||
1282 !sm->PTK_valid) {
1283 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001284 "received EAPOL-Key msg 4/4 in invalid state (%d) - dropped",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001285 sm->wpa_ptk_state);
1286 return;
1287 }
1288 break;
1289 case GROUP_2:
1290 if (sm->wpa_ptk_group_state != WPA_PTK_GROUP_REKEYNEGOTIATING
1291 || !sm->PTK_valid) {
1292 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001293 "received EAPOL-Key msg 2/2 in invalid state (%d) - dropped",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001294 sm->wpa_ptk_group_state);
1295 return;
1296 }
1297 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001298 case REQUEST:
1299 break;
1300 }
1301
1302 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
1303 "received EAPOL-Key frame (%s)", msgtxt);
1304
1305 if (key_info & WPA_KEY_INFO_ACK) {
1306 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
1307 "received invalid EAPOL-Key: Key Ack set");
1308 return;
1309 }
1310
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001311 if (!wpa_key_mgmt_fils(sm->wpa_key_mgmt) &&
1312 !(key_info & WPA_KEY_INFO_MIC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001313 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
1314 "received invalid EAPOL-Key: Key MIC not set");
1315 return;
1316 }
1317
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001318#ifdef CONFIG_FILS
1319 if (wpa_key_mgmt_fils(sm->wpa_key_mgmt) &&
1320 (key_info & WPA_KEY_INFO_MIC)) {
1321 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
1322 "received invalid EAPOL-Key: Key MIC set");
1323 return;
1324 }
1325#endif /* CONFIG_FILS */
1326
Hai Shalome21d4e82020-04-29 16:34:06 -07001327 sm->MICVerified = false;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001328 if (sm->PTK_valid && !sm->update_snonce) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001329 if (mic_len &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001330 wpa_verify_key_mic(sm->wpa_key_mgmt, sm->pmk_len, &sm->PTK,
1331 data, data_len) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001332 (msg != PAIRWISE_4 || !sm->alt_snonce_valid ||
1333 wpa_try_alt_snonce(sm, data, data_len))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001334 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
1335 "received EAPOL-Key with invalid MIC");
Hai Shalom74f70d42019-02-11 14:42:39 -08001336#ifdef TEST_FUZZ
1337 wpa_printf(MSG_INFO,
1338 "TEST: Ignore Key MIC failure for fuzz testing");
1339 goto continue_fuzz;
1340#endif /* TEST_FUZZ */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001341 return;
1342 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001343#ifdef CONFIG_FILS
1344 if (!mic_len &&
1345 wpa_aead_decrypt(sm, &sm->PTK, data, data_len,
1346 &key_data_length) < 0) {
1347 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
1348 "received EAPOL-Key with invalid MIC");
Hai Shalom74f70d42019-02-11 14:42:39 -08001349#ifdef TEST_FUZZ
1350 wpa_printf(MSG_INFO,
1351 "TEST: Ignore Key MIC failure for fuzz testing");
1352 goto continue_fuzz;
1353#endif /* TEST_FUZZ */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001354 return;
1355 }
1356#endif /* CONFIG_FILS */
Hai Shalom74f70d42019-02-11 14:42:39 -08001357#ifdef TEST_FUZZ
1358 continue_fuzz:
1359#endif /* TEST_FUZZ */
Hai Shalome21d4e82020-04-29 16:34:06 -07001360 sm->MICVerified = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001361 eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm);
1362 sm->pending_1_of_4_timeout = 0;
1363 }
1364
1365 if (key_info & WPA_KEY_INFO_REQUEST) {
1366 if (sm->MICVerified) {
1367 sm->req_replay_counter_used = 1;
1368 os_memcpy(sm->req_replay_counter, key->replay_counter,
1369 WPA_REPLAY_COUNTER_LEN);
1370 } else {
1371 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001372 "received EAPOL-Key request with invalid MIC");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001373 return;
1374 }
1375
1376 /*
1377 * TODO: should decrypt key data field if encryption was used;
1378 * even though MAC address KDE is not normally encrypted,
1379 * supplicant is allowed to encrypt it.
1380 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001381 if (key_info & WPA_KEY_INFO_ERROR) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001382 if (wpa_receive_error_report(
1383 wpa_auth, sm,
1384 !(key_info & WPA_KEY_INFO_KEY_TYPE)) > 0)
1385 return; /* STA entry was removed */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001386 } else if (key_info & WPA_KEY_INFO_KEY_TYPE) {
1387 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001388 "received EAPOL-Key Request for new 4-Way Handshake");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001389 wpa_request_new_ptk(sm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001390 } else if (key_data_length > 0 &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001391 wpa_parse_kde_ies(key_data, key_data_length,
1392 &kde) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001393 kde.mac_addr) {
1394 } else {
1395 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001396 "received EAPOL-Key Request for GTK rekeying");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001397 eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL);
Hai Shaloma20dcd72022-02-04 13:43:00 -08001398 if (wpa_auth_gtk_rekey_in_process(wpa_auth))
1399 wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG,
1400 "skip new GTK rekey - already in process");
1401 else
1402 wpa_rekey_gtk(wpa_auth, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001403 }
1404 } else {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001405 /* Do not allow the same key replay counter to be reused. */
1406 wpa_replay_counter_mark_invalid(sm->key_replay,
1407 key->replay_counter);
1408
1409 if (msg == PAIRWISE_2) {
1410 /*
1411 * Maintain a copy of the pending EAPOL-Key frames in
1412 * case the EAPOL-Key frame was retransmitted. This is
1413 * needed to allow EAPOL-Key msg 2/4 reply to another
1414 * pending msg 1/4 to update the SNonce to work around
1415 * unexpected supplicant behavior.
1416 */
1417 os_memcpy(sm->prev_key_replay, sm->key_replay,
1418 sizeof(sm->key_replay));
1419 } else {
1420 os_memset(sm->prev_key_replay, 0,
1421 sizeof(sm->prev_key_replay));
1422 }
1423
1424 /*
1425 * Make sure old valid counters are not accepted anymore and
1426 * do not get copied again.
1427 */
1428 wpa_replay_counter_mark_invalid(sm->key_replay, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001429 }
1430
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001431 os_free(sm->last_rx_eapol_key);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001432 sm->last_rx_eapol_key = os_memdup(data, data_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07001433 if (!sm->last_rx_eapol_key)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001434 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001435 sm->last_rx_eapol_key_len = data_len;
1436
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001437 sm->rx_eapol_key_secure = !!(key_info & WPA_KEY_INFO_SECURE);
Hai Shalome21d4e82020-04-29 16:34:06 -07001438 sm->EAPOLKeyReceived = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001439 sm->EAPOLKeyPairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE);
1440 sm->EAPOLKeyRequest = !!(key_info & WPA_KEY_INFO_REQUEST);
1441 os_memcpy(sm->SNonce, key->key_nonce, WPA_NONCE_LEN);
1442 wpa_sm_step(sm);
1443}
1444
1445
1446static int wpa_gmk_to_gtk(const u8 *gmk, const char *label, const u8 *addr,
1447 const u8 *gnonce, u8 *gtk, size_t gtk_len)
1448{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001449 u8 data[ETH_ALEN + WPA_NONCE_LEN + 8 + WPA_GTK_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001450 u8 *pos;
1451 int ret = 0;
1452
1453 /* GTK = PRF-X(GMK, "Group key expansion",
1454 * AA || GNonce || Time || random data)
1455 * The example described in the IEEE 802.11 standard uses only AA and
1456 * GNonce as inputs here. Add some more entropy since this derivation
1457 * is done only at the Authenticator and as such, does not need to be
1458 * exactly same.
1459 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001460 os_memset(data, 0, sizeof(data));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001461 os_memcpy(data, addr, ETH_ALEN);
1462 os_memcpy(data + ETH_ALEN, gnonce, WPA_NONCE_LEN);
1463 pos = data + ETH_ALEN + WPA_NONCE_LEN;
1464 wpa_get_ntp_timestamp(pos);
Hai Shalom74f70d42019-02-11 14:42:39 -08001465#ifdef TEST_FUZZ
1466 os_memset(pos, 0xef, 8);
1467#endif /* TEST_FUZZ */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001468 pos += 8;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001469 if (random_get_bytes(pos, gtk_len) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001470 ret = -1;
1471
Roshan Pius3a1667e2018-07-03 15:17:14 -07001472#ifdef CONFIG_SHA384
1473 if (sha384_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data),
1474 gtk, gtk_len) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001475 ret = -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001476#else /* CONFIG_SHA384 */
1477#ifdef CONFIG_SHA256
1478 if (sha256_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data),
1479 gtk, gtk_len) < 0)
1480 ret = -1;
1481#else /* CONFIG_SHA256 */
1482 if (sha1_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data),
1483 gtk, gtk_len) < 0)
1484 ret = -1;
1485#endif /* CONFIG_SHA256 */
1486#endif /* CONFIG_SHA384 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001487
Hai Shalom81f62d82019-07-22 12:10:00 -07001488 forced_memzero(data, sizeof(data));
1489
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001490 return ret;
1491}
1492
1493
1494static void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx)
1495{
1496 struct wpa_authenticator *wpa_auth = eloop_ctx;
1497 struct wpa_state_machine *sm = timeout_ctx;
1498
Sunil Ravia04bd252022-05-02 22:54:18 -07001499 if (sm->waiting_radius_psk) {
1500 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
1501 "Ignore EAPOL-Key timeout while waiting for RADIUS PSK");
1502 return;
1503 }
1504
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001505 sm->pending_1_of_4_timeout = 0;
1506 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "EAPOL-Key timeout");
Hai Shalome21d4e82020-04-29 16:34:06 -07001507 sm->TimeoutEvt = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001508 wpa_sm_step(sm);
1509}
1510
1511
1512void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
1513 struct wpa_state_machine *sm, int key_info,
1514 const u8 *key_rsc, const u8 *nonce,
1515 const u8 *kde, size_t kde_len,
1516 int keyidx, int encr, int force_version)
1517{
Hai Shalomfdcde762020-04-02 11:19:20 -07001518 struct wpa_auth_config *conf = &wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001519 struct ieee802_1x_hdr *hdr;
1520 struct wpa_eapol_key *key;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001521 size_t len, mic_len, keyhdrlen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001522 int alg;
1523 int key_data_len, pad_len = 0;
1524 u8 *buf, *pos;
1525 int version, pairwise;
1526 int i;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001527 u8 *key_mic, *key_data;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001528
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001529 mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001530 keyhdrlen = sizeof(*key) + mic_len + 2;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001531
1532 len = sizeof(struct ieee802_1x_hdr) + keyhdrlen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001533
1534 if (force_version)
1535 version = force_version;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001536 else if (wpa_use_akm_defined(sm->wpa_key_mgmt))
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001537 version = WPA_KEY_INFO_TYPE_AKM_DEFINED;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001538 else if (wpa_use_cmac(sm->wpa_key_mgmt))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001539 version = WPA_KEY_INFO_TYPE_AES_128_CMAC;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001540 else if (sm->pairwise != WPA_CIPHER_TKIP)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001541 version = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;
1542 else
1543 version = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
1544
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001545 pairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001546
Hai Shalomfdcde762020-04-02 11:19:20 -07001547 wpa_printf(MSG_DEBUG,
1548 "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 -07001549 version,
1550 (key_info & WPA_KEY_INFO_SECURE) ? 1 : 0,
1551 (key_info & WPA_KEY_INFO_MIC) ? 1 : 0,
1552 (key_info & WPA_KEY_INFO_ACK) ? 1 : 0,
1553 (key_info & WPA_KEY_INFO_INSTALL) ? 1 : 0,
Hai Shalomfdcde762020-04-02 11:19:20 -07001554 pairwise, kde_len, keyidx, encr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001555
1556 key_data_len = kde_len;
1557
1558 if ((version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
Roshan Pius3a1667e2018-07-03 15:17:14 -07001559 wpa_use_aes_key_wrap(sm->wpa_key_mgmt) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001560 version == WPA_KEY_INFO_TYPE_AES_128_CMAC) && encr) {
1561 pad_len = key_data_len % 8;
1562 if (pad_len)
1563 pad_len = 8 - pad_len;
1564 key_data_len += pad_len + 8;
1565 }
1566
1567 len += key_data_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001568 if (!mic_len && encr)
1569 len += AES_BLOCK_SIZE;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001570
1571 hdr = os_zalloc(len);
Hai Shalomfdcde762020-04-02 11:19:20 -07001572 if (!hdr)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001573 return;
Hai Shalomfdcde762020-04-02 11:19:20 -07001574 hdr->version = conf->eapol_version;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001575 hdr->type = IEEE802_1X_TYPE_EAPOL_KEY;
1576 hdr->length = host_to_be16(len - sizeof(*hdr));
1577 key = (struct wpa_eapol_key *) (hdr + 1);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001578 key_mic = (u8 *) (key + 1);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001579 key_data = ((u8 *) (hdr + 1)) + keyhdrlen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001580
1581 key->type = sm->wpa == WPA_VERSION_WPA2 ?
1582 EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
1583 key_info |= version;
1584 if (encr && sm->wpa == WPA_VERSION_WPA2)
1585 key_info |= WPA_KEY_INFO_ENCR_KEY_DATA;
1586 if (sm->wpa != WPA_VERSION_WPA2)
1587 key_info |= keyidx << WPA_KEY_INFO_KEY_INDEX_SHIFT;
1588 WPA_PUT_BE16(key->key_info, key_info);
1589
Hai Shalomfdcde762020-04-02 11:19:20 -07001590 alg = pairwise ? sm->pairwise : conf->wpa_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001591 if (sm->wpa == WPA_VERSION_WPA2 && !pairwise)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001592 WPA_PUT_BE16(key->key_length, 0);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001593 else
1594 WPA_PUT_BE16(key->key_length, wpa_cipher_key_len(alg));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001595
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001596 for (i = RSNA_MAX_EAPOL_RETRIES - 1; i > 0; i--) {
1597 sm->key_replay[i].valid = sm->key_replay[i - 1].valid;
1598 os_memcpy(sm->key_replay[i].counter,
1599 sm->key_replay[i - 1].counter,
1600 WPA_REPLAY_COUNTER_LEN);
1601 }
1602 inc_byte_array(sm->key_replay[0].counter, WPA_REPLAY_COUNTER_LEN);
1603 os_memcpy(key->replay_counter, sm->key_replay[0].counter,
1604 WPA_REPLAY_COUNTER_LEN);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001605 wpa_hexdump(MSG_DEBUG, "WPA: Replay Counter",
1606 key->replay_counter, WPA_REPLAY_COUNTER_LEN);
Hai Shalome21d4e82020-04-29 16:34:06 -07001607 sm->key_replay[0].valid = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001608
1609 if (nonce)
1610 os_memcpy(key->key_nonce, nonce, WPA_NONCE_LEN);
1611
1612 if (key_rsc)
1613 os_memcpy(key->key_rsc, key_rsc, WPA_KEY_RSC_LEN);
1614
1615 if (kde && !encr) {
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001616 os_memcpy(key_data, kde, kde_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001617 WPA_PUT_BE16(key_mic + mic_len, kde_len);
1618#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07001619 } else if (!mic_len && kde) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001620 const u8 *aad[1];
1621 size_t aad_len[1];
1622
1623 WPA_PUT_BE16(key_mic, AES_BLOCK_SIZE + kde_len);
1624 wpa_hexdump_key(MSG_DEBUG, "Plaintext EAPOL-Key Key Data",
1625 kde, kde_len);
1626
1627 wpa_hexdump_key(MSG_DEBUG, "WPA: KEK",
1628 sm->PTK.kek, sm->PTK.kek_len);
1629 /* AES-SIV AAD from EAPOL protocol version field (inclusive) to
1630 * to Key Data (exclusive). */
1631 aad[0] = (u8 *) hdr;
1632 aad_len[0] = key_mic + 2 - (u8 *) hdr;
1633 if (aes_siv_encrypt(sm->PTK.kek, sm->PTK.kek_len, kde, kde_len,
1634 1, aad, aad_len, key_mic + 2) < 0) {
1635 wpa_printf(MSG_DEBUG, "WPA: AES-SIV encryption failed");
1636 return;
1637 }
1638
1639 wpa_hexdump(MSG_DEBUG, "WPA: Encrypted Key Data from SIV",
1640 key_mic + 2, AES_BLOCK_SIZE + kde_len);
1641#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001642 } else if (encr && kde) {
1643 buf = os_zalloc(key_data_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07001644 if (!buf) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001645 os_free(hdr);
1646 return;
1647 }
1648 pos = buf;
1649 os_memcpy(pos, kde, kde_len);
1650 pos += kde_len;
1651
1652 if (pad_len)
1653 *pos++ = 0xdd;
1654
1655 wpa_hexdump_key(MSG_DEBUG, "Plaintext EAPOL-Key Key Data",
1656 buf, key_data_len);
1657 if (version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
Roshan Pius3a1667e2018-07-03 15:17:14 -07001658 wpa_use_aes_key_wrap(sm->wpa_key_mgmt) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001659 version == WPA_KEY_INFO_TYPE_AES_128_CMAC) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001660 wpa_printf(MSG_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07001661 "WPA: Encrypt Key Data using AES-WRAP (KEK length %zu)",
1662 sm->PTK.kek_len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001663 if (aes_wrap(sm->PTK.kek, sm->PTK.kek_len,
1664 (key_data_len - 8) / 8, buf, key_data)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001665 os_free(hdr);
Sunil Ravia04bd252022-05-02 22:54:18 -07001666 bin_clear_free(buf, key_data_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001667 return;
1668 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001669 WPA_PUT_BE16(key_mic + mic_len, key_data_len);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001670#ifndef CONFIG_NO_RC4
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001671 } else if (sm->PTK.kek_len == 16) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001672 u8 ek[32];
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001673
1674 wpa_printf(MSG_DEBUG,
1675 "WPA: Encrypt Key Data using RC4");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001676 os_memcpy(key->key_iv,
1677 sm->group->Counter + WPA_NONCE_LEN - 16, 16);
1678 inc_byte_array(sm->group->Counter, WPA_NONCE_LEN);
1679 os_memcpy(ek, key->key_iv, 16);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001680 os_memcpy(ek + 16, sm->PTK.kek, sm->PTK.kek_len);
1681 os_memcpy(key_data, buf, key_data_len);
1682 rc4_skip(ek, 32, 256, key_data, key_data_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001683 WPA_PUT_BE16(key_mic + mic_len, key_data_len);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001684#endif /* CONFIG_NO_RC4 */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001685 } else {
1686 os_free(hdr);
Sunil Ravia04bd252022-05-02 22:54:18 -07001687 bin_clear_free(buf, key_data_len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001688 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001689 }
Sunil Ravia04bd252022-05-02 22:54:18 -07001690 bin_clear_free(buf, key_data_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001691 }
1692
1693 if (key_info & WPA_KEY_INFO_MIC) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001694 if (!sm->PTK_valid || !mic_len) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001695 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07001696 "PTK not valid when sending EAPOL-Key frame");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001697 os_free(hdr);
1698 return;
1699 }
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001700
Roshan Pius3a1667e2018-07-03 15:17:14 -07001701 if (wpa_eapol_key_mic(sm->PTK.kck, sm->PTK.kck_len,
1702 sm->wpa_key_mgmt, version,
1703 (u8 *) hdr, len, key_mic) < 0) {
1704 os_free(hdr);
1705 return;
1706 }
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001707#ifdef CONFIG_TESTING_OPTIONS
1708 if (!pairwise &&
Hai Shalomfdcde762020-04-02 11:19:20 -07001709 conf->corrupt_gtk_rekey_mic_probability > 0.0 &&
1710 drand48() < conf->corrupt_gtk_rekey_mic_probability) {
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001711 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
1712 "Corrupting group EAPOL-Key Key MIC");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001713 key_mic[0]++;
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001714 }
1715#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001716 }
1717
Hai Shalomfdcde762020-04-02 11:19:20 -07001718 wpa_auth_set_eapol(wpa_auth, sm->addr, WPA_EAPOL_inc_EapolFramesTx, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001719 wpa_auth_send_eapol(wpa_auth, sm->addr, (u8 *) hdr, len,
Kai Shie75b0652020-11-24 20:31:29 -08001720 sm->pairwise_set);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001721 os_free(hdr);
1722}
1723
1724
1725static void wpa_send_eapol(struct wpa_authenticator *wpa_auth,
1726 struct wpa_state_machine *sm, int key_info,
1727 const u8 *key_rsc, const u8 *nonce,
1728 const u8 *kde, size_t kde_len,
1729 int keyidx, int encr)
1730{
1731 int timeout_ms;
1732 int pairwise = key_info & WPA_KEY_INFO_KEY_TYPE;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001733 u32 ctr;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001734
Hai Shalomfdcde762020-04-02 11:19:20 -07001735 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001736 return;
1737
1738 __wpa_send_eapol(wpa_auth, sm, key_info, key_rsc, nonce, kde, kde_len,
1739 keyidx, encr, 0);
1740
1741 ctr = pairwise ? sm->TimeoutCtr : sm->GTimeoutCtr;
1742 if (ctr == 1 && wpa_auth->conf.tx_status)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001743 timeout_ms = pairwise ? eapol_key_timeout_first :
1744 eapol_key_timeout_first_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001745 else
1746 timeout_ms = eapol_key_timeout_subseq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001747 if (wpa_auth->conf.wpa_disable_eapol_key_retries &&
1748 (!pairwise || (key_info & WPA_KEY_INFO_MIC)))
1749 timeout_ms = eapol_key_timeout_no_retrans;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001750 if (pairwise && ctr == 1 && !(key_info & WPA_KEY_INFO_MIC))
1751 sm->pending_1_of_4_timeout = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08001752#ifdef TEST_FUZZ
1753 timeout_ms = 1;
1754#endif /* TEST_FUZZ */
Kai Shie75b0652020-11-24 20:31:29 -08001755#ifdef CONFIG_TESTING_OPTIONS
1756 if(wpa_auth->conf.enable_eapol_large_timeout) {
1757 timeout_ms = 50 * 1000;
1758 }
1759#endif
Hai Shalomfdcde762020-04-02 11:19:20 -07001760 wpa_printf(MSG_DEBUG,
1761 "WPA: Use EAPOL-Key timeout of %u ms (retry counter %u)",
1762 timeout_ms, ctr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001763 eloop_register_timeout(timeout_ms / 1000, (timeout_ms % 1000) * 1000,
1764 wpa_send_eapol_timeout, wpa_auth, sm);
1765}
1766
1767
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001768static int wpa_verify_key_mic(int akmp, size_t pmk_len, struct wpa_ptk *PTK,
1769 u8 *data, size_t data_len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001770{
1771 struct ieee802_1x_hdr *hdr;
1772 struct wpa_eapol_key *key;
1773 u16 key_info;
1774 int ret = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001775 u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN], *mic_pos;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001776 size_t mic_len = wpa_mic_len(akmp, pmk_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001777
1778 if (data_len < sizeof(*hdr) + sizeof(*key))
1779 return -1;
1780
1781 hdr = (struct ieee802_1x_hdr *) data;
1782 key = (struct wpa_eapol_key *) (hdr + 1);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001783 mic_pos = (u8 *) (key + 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001784 key_info = WPA_GET_BE16(key->key_info);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001785 os_memcpy(mic, mic_pos, mic_len);
1786 os_memset(mic_pos, 0, mic_len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001787 if (wpa_eapol_key_mic(PTK->kck, PTK->kck_len, akmp,
1788 key_info & WPA_KEY_INFO_TYPE_MASK,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001789 data, data_len, mic_pos) ||
1790 os_memcmp_const(mic, mic_pos, mic_len) != 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001791 ret = -1;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001792 os_memcpy(mic_pos, mic, mic_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001793 return ret;
1794}
1795
1796
1797void wpa_remove_ptk(struct wpa_state_machine *sm)
1798{
Hai Shalome21d4e82020-04-29 16:34:06 -07001799 sm->PTK_valid = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001800 os_memset(&sm->PTK, 0, sizeof(sm->PTK));
Hai Shalom60840252021-02-19 19:02:11 -08001801
1802 wpa_auth_remove_ptksa(sm->wpa_auth, sm->addr, sm->pairwise);
1803
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001804 if (wpa_auth_set_key(sm->wpa_auth, 0, WPA_ALG_NONE, sm->addr, 0, NULL,
Hai Shalomfdcde762020-04-02 11:19:20 -07001805 0, KEY_FLAG_PAIRWISE))
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001806 wpa_printf(MSG_DEBUG,
1807 "RSN: PTK removal from the driver failed");
Hai Shalomfdcde762020-04-02 11:19:20 -07001808 if (sm->use_ext_key_id &&
1809 wpa_auth_set_key(sm->wpa_auth, 0, WPA_ALG_NONE, sm->addr, 1, NULL,
1810 0, KEY_FLAG_PAIRWISE))
1811 wpa_printf(MSG_DEBUG,
1812 "RSN: PTK Key ID 1 removal from the driver failed");
Hai Shalome21d4e82020-04-29 16:34:06 -07001813 sm->pairwise_set = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001814 eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm);
1815}
1816
1817
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001818int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001819{
1820 int remove_ptk = 1;
1821
Hai Shalomfdcde762020-04-02 11:19:20 -07001822 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001823 return -1;
1824
1825 wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
1826 "event %d notification", event);
1827
1828 switch (event) {
1829 case WPA_AUTH:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001830#ifdef CONFIG_MESH
1831 /* PTKs are derived through AMPE */
1832 if (wpa_auth_start_ampe(sm->wpa_auth, sm->addr)) {
1833 /* not mesh */
1834 break;
1835 }
1836 return 0;
1837#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001838 case WPA_ASSOC:
1839 break;
1840 case WPA_DEAUTH:
1841 case WPA_DISASSOC:
Hai Shalome21d4e82020-04-29 16:34:06 -07001842 sm->DeauthenticationRequest = true;
Hai Shalom1dc4d202019-04-29 16:22:27 -07001843 os_memset(sm->PMK, 0, sizeof(sm->PMK));
1844 sm->pmk_len = 0;
Sunil Ravia04bd252022-05-02 22:54:18 -07001845#ifdef CONFIG_IEEE80211R_AP
Hai Shalom1dc4d202019-04-29 16:22:27 -07001846 os_memset(sm->xxkey, 0, sizeof(sm->xxkey));
1847 sm->xxkey_len = 0;
Hai Shalom81f62d82019-07-22 12:10:00 -07001848 os_memset(sm->pmk_r1, 0, sizeof(sm->pmk_r1));
1849 sm->pmk_r1_len = 0;
Hai Shalom1dc4d202019-04-29 16:22:27 -07001850#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001851 break;
1852 case WPA_REAUTH:
1853 case WPA_REAUTH_EAPOL:
1854 if (!sm->started) {
1855 /*
1856 * When using WPS, we may end up here if the STA
1857 * manages to re-associate without the previous STA
1858 * entry getting removed. Consequently, we need to make
1859 * sure that the WPA state machines gets initialized
1860 * properly at this point.
1861 */
Hai Shalomfdcde762020-04-02 11:19:20 -07001862 wpa_printf(MSG_DEBUG,
1863 "WPA state machine had not been started - initialize now");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001864 sm->started = 1;
Hai Shalome21d4e82020-04-29 16:34:06 -07001865 sm->Init = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001866 if (wpa_sm_step(sm) == 1)
1867 return 1; /* should not really happen */
Hai Shalome21d4e82020-04-29 16:34:06 -07001868 sm->Init = false;
1869 sm->AuthenticationRequest = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001870 break;
1871 }
Hai Shalomfdcde762020-04-02 11:19:20 -07001872
Sunil Ravia04bd252022-05-02 22:54:18 -07001873 if (sm->ptkstart_without_success > 3) {
1874 wpa_printf(MSG_INFO,
1875 "WPA: Multiple EAP reauth attempts without 4-way handshake completion, disconnect "
1876 MACSTR, MAC2STR(sm->addr));
1877 sm->Disconnect = true;
1878 break;
1879 }
1880
Hai Shalomfdcde762020-04-02 11:19:20 -07001881 if (!sm->use_ext_key_id &&
1882 sm->wpa_auth->conf.wpa_deny_ptk0_rekey) {
1883 wpa_printf(MSG_INFO,
1884 "WPA: PTK0 rekey not allowed, disconnect "
1885 MACSTR, MAC2STR(sm->addr));
Hai Shalome21d4e82020-04-29 16:34:06 -07001886 sm->Disconnect = true;
Hai Shalomfdcde762020-04-02 11:19:20 -07001887 /* Try to encourage the STA to reconnect */
1888 sm->disconnect_reason =
1889 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA;
1890 break;
1891 }
1892
1893 if (sm->use_ext_key_id)
1894 sm->keyidx_active ^= 1; /* flip Key ID */
1895
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001896 if (sm->GUpdateStationKeys) {
1897 /*
1898 * Reauthentication cancels the pending group key
1899 * update for this STA.
1900 */
1901 sm->group->GKeyDoneStations--;
Hai Shalome21d4e82020-04-29 16:34:06 -07001902 sm->GUpdateStationKeys = false;
1903 sm->PtkGroupInit = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001904 }
Hai Shalome21d4e82020-04-29 16:34:06 -07001905 sm->ReAuthenticationRequest = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001906 break;
1907 case WPA_ASSOC_FT:
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001908#ifdef CONFIG_IEEE80211R_AP
Hai Shalomfdcde762020-04-02 11:19:20 -07001909 wpa_printf(MSG_DEBUG,
1910 "FT: Retry PTK configuration after association");
Hai Shalomb755a2a2020-04-23 21:49:02 -07001911 wpa_ft_install_ptk(sm, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001912
1913 /* Using FT protocol, not WPA auth state machine */
1914 sm->ft_completed = 1;
Hai Shalom81f62d82019-07-22 12:10:00 -07001915 wpa_auth_set_ptk_rekey_timer(sm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001916 return 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001917#else /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001918 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001919#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001920 case WPA_ASSOC_FILS:
1921#ifdef CONFIG_FILS
1922 wpa_printf(MSG_DEBUG,
1923 "FILS: TK configuration after association");
1924 fils_set_tk(sm);
1925 sm->fils_completed = 1;
1926 return 0;
1927#else /* CONFIG_FILS */
1928 break;
1929#endif /* CONFIG_FILS */
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02001930 case WPA_DRV_STA_REMOVED:
Hai Shalome21d4e82020-04-29 16:34:06 -07001931 sm->tk_already_set = false;
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02001932 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001933 }
1934
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001935#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001936 sm->ft_completed = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001937#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001938
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001939 if (sm->mgmt_frame_prot && event == WPA_AUTH)
1940 remove_ptk = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001941#ifdef CONFIG_FILS
1942 if (wpa_key_mgmt_fils(sm->wpa_key_mgmt) &&
1943 (event == WPA_AUTH || event == WPA_ASSOC))
1944 remove_ptk = 0;
1945#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001946
1947 if (remove_ptk) {
Hai Shalome21d4e82020-04-29 16:34:06 -07001948 sm->PTK_valid = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001949 os_memset(&sm->PTK, 0, sizeof(sm->PTK));
1950
1951 if (event != WPA_REAUTH_EAPOL)
1952 wpa_remove_ptk(sm);
1953 }
1954
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001955 if (sm->in_step_loop) {
1956 /*
1957 * wpa_sm_step() is already running - avoid recursive call to
1958 * it by making the existing loop process the new update.
1959 */
Hai Shalome21d4e82020-04-29 16:34:06 -07001960 sm->changed = true;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001961 return 0;
1962 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001963 return wpa_sm_step(sm);
1964}
1965
1966
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001967SM_STATE(WPA_PTK, INITIALIZE)
1968{
1969 SM_ENTRY_MA(WPA_PTK, INITIALIZE, wpa_ptk);
1970 if (sm->Init) {
1971 /* Init flag is not cleared here, so avoid busy
1972 * loop by claiming nothing changed. */
Hai Shalome21d4e82020-04-29 16:34:06 -07001973 sm->changed = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001974 }
1975
1976 sm->keycount = 0;
1977 if (sm->GUpdateStationKeys)
1978 sm->group->GKeyDoneStations--;
Hai Shalome21d4e82020-04-29 16:34:06 -07001979 sm->GUpdateStationKeys = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001980 if (sm->wpa == WPA_VERSION_WPA)
Hai Shalome21d4e82020-04-29 16:34:06 -07001981 sm->PInitAKeys = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001982 if (1 /* Unicast cipher supported AND (ESS OR ((IBSS or WDS) and
1983 * Local AA > Remote AA)) */) {
Hai Shalome21d4e82020-04-29 16:34:06 -07001984 sm->Pair = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001985 }
1986 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 0);
1987 wpa_remove_ptk(sm);
1988 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid, 0);
1989 sm->TimeoutCtr = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001990 if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
1991 sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP ||
1992 sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001993 wpa_auth_set_eapol(sm->wpa_auth, sm->addr,
1994 WPA_EAPOL_authorized, 0);
1995 }
1996}
1997
1998
1999SM_STATE(WPA_PTK, DISCONNECT)
2000{
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002001 u16 reason = sm->disconnect_reason;
2002
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002003 SM_ENTRY_MA(WPA_PTK, DISCONNECT, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07002004 sm->Disconnect = false;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002005 sm->disconnect_reason = 0;
2006 if (!reason)
2007 reason = WLAN_REASON_PREV_AUTH_NOT_VALID;
2008 wpa_sta_disconnect(sm->wpa_auth, sm->addr, reason);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002009}
2010
2011
2012SM_STATE(WPA_PTK, DISCONNECTED)
2013{
2014 SM_ENTRY_MA(WPA_PTK, DISCONNECTED, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07002015 sm->DeauthenticationRequest = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002016}
2017
2018
2019SM_STATE(WPA_PTK, AUTHENTICATION)
2020{
2021 SM_ENTRY_MA(WPA_PTK, AUTHENTICATION, wpa_ptk);
2022 os_memset(&sm->PTK, 0, sizeof(sm->PTK));
Hai Shalome21d4e82020-04-29 16:34:06 -07002023 sm->PTK_valid = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002024 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portControl_Auto,
2025 1);
2026 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 1);
Hai Shalome21d4e82020-04-29 16:34:06 -07002027 sm->AuthenticationRequest = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002028}
2029
2030
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002031static void wpa_group_ensure_init(struct wpa_authenticator *wpa_auth,
2032 struct wpa_group *group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002033{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002034 if (group->first_sta_seen)
2035 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002036 /*
2037 * System has run bit further than at the time hostapd was started
2038 * potentially very early during boot up. This provides better chances
2039 * of collecting more randomness on embedded systems. Re-initialize the
2040 * GMK and Counter here to improve their strength if there was not
2041 * enough entropy available immediately after system startup.
2042 */
Hai Shalomfdcde762020-04-02 11:19:20 -07002043 wpa_printf(MSG_DEBUG,
2044 "WPA: Re-initialize GMK/Counter on first station");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002045 if (random_pool_ready() != 1) {
Hai Shalomfdcde762020-04-02 11:19:20 -07002046 wpa_printf(MSG_INFO,
2047 "WPA: Not enough entropy in random pool to proceed - reject first 4-way handshake");
Hai Shalome21d4e82020-04-29 16:34:06 -07002048 group->reject_4way_hs_for_entropy = true;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002049 } else {
Hai Shalome21d4e82020-04-29 16:34:06 -07002050 group->first_sta_seen = true;
2051 group->reject_4way_hs_for_entropy = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002052 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002053
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002054 if (wpa_group_init_gmk_and_counter(wpa_auth, group) < 0 ||
2055 wpa_gtk_update(wpa_auth, group) < 0 ||
2056 wpa_group_config_group_keys(wpa_auth, group) < 0) {
2057 wpa_printf(MSG_INFO, "WPA: GMK/GTK setup failed");
Hai Shalome21d4e82020-04-29 16:34:06 -07002058 group->first_sta_seen = false;
2059 group->reject_4way_hs_for_entropy = true;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002060 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002061}
2062
2063
2064SM_STATE(WPA_PTK, AUTHENTICATION2)
2065{
2066 SM_ENTRY_MA(WPA_PTK, AUTHENTICATION2, wpa_ptk);
2067
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002068 wpa_group_ensure_init(sm->wpa_auth, sm->group);
Hai Shalome21d4e82020-04-29 16:34:06 -07002069 sm->ReAuthenticationRequest = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002070
Dmitry Shmidt04949592012-07-19 12:16:46 -07002071 /*
2072 * Definition of ANonce selection in IEEE Std 802.11i-2004 is somewhat
2073 * ambiguous. The Authenticator state machine uses a counter that is
2074 * incremented by one for each 4-way handshake. However, the security
2075 * analysis of 4-way handshake points out that unpredictable nonces
2076 * help in preventing precomputation attacks. Instead of the state
2077 * machine definition, use an unpredictable nonce value here to provide
2078 * stronger protection against potential precomputation attacks.
2079 */
2080 if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) {
Hai Shalomfdcde762020-04-02 11:19:20 -07002081 wpa_printf(MSG_ERROR,
2082 "WPA: Failed to get random data for ANonce.");
Hai Shalome21d4e82020-04-29 16:34:06 -07002083 sm->Disconnect = true;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002084 return;
2085 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002086 wpa_hexdump(MSG_DEBUG, "WPA: Assign ANonce", sm->ANonce,
2087 WPA_NONCE_LEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002088 /* IEEE 802.11i does not clear TimeoutCtr here, but this is more
2089 * logical place than INITIALIZE since AUTHENTICATION2 can be
2090 * re-entered on ReAuthenticationRequest without going through
2091 * INITIALIZE. */
2092 sm->TimeoutCtr = 0;
2093}
2094
2095
Jouni Malinen1420a892017-10-01 12:32:57 +03002096static int wpa_auth_sm_ptk_update(struct wpa_state_machine *sm)
2097{
2098 if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) {
2099 wpa_printf(MSG_ERROR,
2100 "WPA: Failed to get random data for ANonce");
Hai Shalome21d4e82020-04-29 16:34:06 -07002101 sm->Disconnect = true;
Jouni Malinen1420a892017-10-01 12:32:57 +03002102 return -1;
2103 }
2104 wpa_hexdump(MSG_DEBUG, "WPA: Assign new ANonce", sm->ANonce,
2105 WPA_NONCE_LEN);
2106 sm->TimeoutCtr = 0;
2107 return 0;
2108}
2109
2110
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002111SM_STATE(WPA_PTK, INITPMK)
2112{
2113 u8 msk[2 * PMK_LEN];
2114 size_t len = 2 * PMK_LEN;
2115
2116 SM_ENTRY_MA(WPA_PTK, INITPMK, wpa_ptk);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002117#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002118 sm->xxkey_len = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002119#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002120 if (sm->pmksa) {
2121 wpa_printf(MSG_DEBUG, "WPA: PMK from PMKSA cache");
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002122 os_memcpy(sm->PMK, sm->pmksa->pmk, sm->pmksa->pmk_len);
2123 sm->pmk_len = sm->pmksa->pmk_len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002124#ifdef CONFIG_DPP
2125 } else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP) {
2126 wpa_printf(MSG_DEBUG,
2127 "DPP: No PMKSA cache entry for STA - reject connection");
Hai Shalome21d4e82020-04-29 16:34:06 -07002128 sm->Disconnect = true;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002129 sm->disconnect_reason = WLAN_REASON_INVALID_PMKID;
2130 return;
2131#endif /* CONFIG_DPP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002132 } else if (wpa_auth_get_msk(sm->wpa_auth, sm->addr, msk, &len) == 0) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002133 unsigned int pmk_len;
2134
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002135 if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002136 pmk_len = PMK_LEN_SUITE_B_192;
2137 else
2138 pmk_len = PMK_LEN;
Hai Shalomfdcde762020-04-02 11:19:20 -07002139 wpa_printf(MSG_DEBUG,
2140 "WPA: PMK from EAPOL state machine (MSK len=%zu PMK len=%u)",
2141 len, pmk_len);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002142 if (len < pmk_len) {
2143 wpa_printf(MSG_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07002144 "WPA: MSK not long enough (%zu) to create PMK (%u)",
2145 len, pmk_len);
Hai Shalome21d4e82020-04-29 16:34:06 -07002146 sm->Disconnect = true;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002147 return;
2148 }
2149 os_memcpy(sm->PMK, msk, pmk_len);
2150 sm->pmk_len = pmk_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002151#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002152 if (len >= 2 * PMK_LEN) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002153 if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) {
2154 os_memcpy(sm->xxkey, msk, SHA384_MAC_LEN);
2155 sm->xxkey_len = SHA384_MAC_LEN;
2156 } else {
2157 os_memcpy(sm->xxkey, msk + PMK_LEN, PMK_LEN);
2158 sm->xxkey_len = PMK_LEN;
2159 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002160 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002161#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002162 } else {
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002163 wpa_printf(MSG_DEBUG, "WPA: Could not get PMK, get_msk: %p",
Paul Stewart092955c2017-02-06 09:13:09 -08002164 sm->wpa_auth->cb->get_msk);
Hai Shalome21d4e82020-04-29 16:34:06 -07002165 sm->Disconnect = true;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002166 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002167 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002168 forced_memzero(msk, sizeof(msk));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002169
2170 sm->req_replay_counter_used = 0;
Hai Shalome21d4e82020-04-29 16:34:06 -07002171 /* IEEE 802.11i does not set keyRun to false, but not doing this
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002172 * will break reauthentication since EAPOL state machines may not be
2173 * get into AUTHENTICATING state that clears keyRun before WPA state
2174 * machine enters AUTHENTICATION2 state and goes immediately to INITPMK
2175 * state and takes PMK from the previously used AAA Key. This will
2176 * eventually fail in 4-Way Handshake because Supplicant uses PMK
Hai Shalome21d4e82020-04-29 16:34:06 -07002177 * derived from the new AAA Key. Setting keyRun = false here seems to
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002178 * be good workaround for this issue. */
Hai Shalome21d4e82020-04-29 16:34:06 -07002179 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyRun, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002180}
2181
2182
2183SM_STATE(WPA_PTK, INITPSK)
2184{
2185 const u8 *psk;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002186 size_t psk_len;
2187
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002188 SM_ENTRY_MA(WPA_PTK, INITPSK, wpa_ptk);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002189 psk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr, NULL,
Hai Shalom021b0b52019-04-10 11:17:58 -07002190 &psk_len, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002191 if (psk) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002192 os_memcpy(sm->PMK, psk, psk_len);
2193 sm->pmk_len = psk_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002194#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002195 os_memcpy(sm->xxkey, psk, PMK_LEN);
2196 sm->xxkey_len = PMK_LEN;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002197#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002198 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002199#ifdef CONFIG_SAE
2200 if (wpa_auth_uses_sae(sm) && sm->pmksa) {
2201 wpa_printf(MSG_DEBUG, "SAE: PMK from PMKSA cache");
2202 os_memcpy(sm->PMK, sm->pmksa->pmk, sm->pmksa->pmk_len);
2203 sm->pmk_len = sm->pmksa->pmk_len;
Hai Shalom021b0b52019-04-10 11:17:58 -07002204#ifdef CONFIG_IEEE80211R_AP
2205 os_memcpy(sm->xxkey, sm->pmksa->pmk, sm->pmksa->pmk_len);
2206 sm->xxkey_len = sm->pmksa->pmk_len;
2207#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002208 }
2209#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002210 sm->req_replay_counter_used = 0;
2211}
2212
2213
2214SM_STATE(WPA_PTK, PTKSTART)
2215{
2216 u8 buf[2 + RSN_SELECTOR_LEN + PMKID_LEN], *pmkid = NULL;
2217 size_t pmkid_len = 0;
Sunil8cd6f4d2022-06-28 18:40:46 +00002218 u16 key_info;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002219
2220 SM_ENTRY_MA(WPA_PTK, PTKSTART, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07002221 sm->PTKRequest = false;
2222 sm->TimeoutEvt = false;
2223 sm->alt_snonce_valid = false;
Sunil Ravia04bd252022-05-02 22:54:18 -07002224 sm->ptkstart_without_success++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002225
2226 sm->TimeoutCtr++;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002227 if (sm->TimeoutCtr > sm->wpa_auth->conf.wpa_pairwise_update_count) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002228 /* No point in sending the EAPOL-Key - we will disconnect
2229 * immediately following this. */
2230 return;
2231 }
2232
2233 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
2234 "sending 1/4 msg of 4-Way Handshake");
2235 /*
Hai Shalomce48b4a2018-09-05 11:41:35 -07002236 * For infrastructure BSS cases, it is better for the AP not to include
2237 * the PMKID KDE in EAPOL-Key msg 1/4 since it could be used to initiate
2238 * offline search for the passphrase/PSK without having to be able to
2239 * capture a 4-way handshake from a STA that has access to the network.
2240 *
2241 * For IBSS cases, addition of PMKID KDE could be considered even with
2242 * WPA2-PSK cases that use multiple PSKs, but only if there is a single
2243 * possible PSK for this STA. However, this should not be done unless
2244 * there is support for using that information on the supplicant side.
2245 * The concern about exposing PMKID unnecessarily in infrastructure BSS
2246 * cases would also apply here, but at least in the IBSS case, this
2247 * would cover a potential real use case.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002248 */
2249 if (sm->wpa == WPA_VERSION_WPA2 &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002250 (wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) ||
2251 (sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE && sm->pmksa) ||
2252 wpa_key_mgmt_sae(sm->wpa_key_mgmt)) &&
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002253 sm->wpa_key_mgmt != WPA_KEY_MGMT_OSEN) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002254 pmkid = buf;
2255 pmkid_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN;
2256 pmkid[0] = WLAN_EID_VENDOR_SPECIFIC;
2257 pmkid[1] = RSN_SELECTOR_LEN + PMKID_LEN;
2258 RSN_SELECTOR_PUT(&pmkid[2], RSN_KEY_DATA_PMKID);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002259 if (sm->pmksa) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002260 wpa_hexdump(MSG_DEBUG,
2261 "RSN: Message 1/4 PMKID from PMKSA entry",
2262 sm->pmksa->pmkid, PMKID_LEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002263 os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN],
2264 sm->pmksa->pmkid, PMKID_LEN);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002265 } else if (wpa_key_mgmt_suite_b(sm->wpa_key_mgmt)) {
2266 /* No KCK available to derive PMKID */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002267 wpa_printf(MSG_DEBUG,
2268 "RSN: No KCK available to derive PMKID for message 1/4");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002269 pmkid = NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -07002270#ifdef CONFIG_FILS
2271 } else if (wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
2272 if (sm->pmkid_set) {
2273 wpa_hexdump(MSG_DEBUG,
2274 "RSN: Message 1/4 PMKID from FILS/ERP",
2275 sm->pmkid, PMKID_LEN);
2276 os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN],
2277 sm->pmkid, PMKID_LEN);
2278 } else {
2279 /* No PMKID available */
2280 wpa_printf(MSG_DEBUG,
2281 "RSN: No FILS/ERP PMKID available for message 1/4");
2282 pmkid = NULL;
2283 }
2284#endif /* CONFIG_FILS */
2285#ifdef CONFIG_IEEE80211R_AP
2286 } else if (wpa_key_mgmt_ft(sm->wpa_key_mgmt) &&
2287 sm->ft_completed) {
2288 wpa_printf(MSG_DEBUG,
2289 "FT: No PMKID in message 1/4 when using FT protocol");
2290 pmkid = NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -07002291#endif /* CONFIG_IEEE80211R_AP */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002292#ifdef CONFIG_SAE
2293 } else if (wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
2294 if (sm->pmkid_set) {
2295 wpa_hexdump(MSG_DEBUG,
2296 "RSN: Message 1/4 PMKID from SAE",
2297 sm->pmkid, PMKID_LEN);
2298 os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN],
2299 sm->pmkid, PMKID_LEN);
2300 } else {
2301 /* No PMKID available */
2302 wpa_printf(MSG_DEBUG,
2303 "RSN: No SAE PMKID available for message 1/4");
2304 pmkid = NULL;
2305 }
2306#endif /* CONFIG_SAE */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002307 } else {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002308 /*
2309 * Calculate PMKID since no PMKSA cache entry was
2310 * available with pre-calculated PMKID.
2311 */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002312 rsn_pmkid(sm->PMK, sm->pmk_len, sm->wpa_auth->addr,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002313 sm->addr, &pmkid[2 + RSN_SELECTOR_LEN],
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002314 sm->wpa_key_mgmt);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002315 wpa_hexdump(MSG_DEBUG,
2316 "RSN: Message 1/4 PMKID derived from PMK",
2317 &pmkid[2 + RSN_SELECTOR_LEN], PMKID_LEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002318 }
2319 }
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002320 if (!pmkid)
2321 pmkid_len = 0;
Sunil8cd6f4d2022-06-28 18:40:46 +00002322 key_info = WPA_KEY_INFO_ACK | WPA_KEY_INFO_KEY_TYPE;
2323 if (sm->pairwise_set && sm->wpa != WPA_VERSION_WPA)
2324 key_info |= WPA_KEY_INFO_SECURE;
2325 wpa_send_eapol(sm->wpa_auth, sm, key_info, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002326 sm->ANonce, pmkid, pmkid_len, 0, 0);
2327}
2328
2329
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002330static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002331 const u8 *pmk, unsigned int pmk_len,
Hai Shalomfdcde762020-04-02 11:19:20 -07002332 struct wpa_ptk *ptk, int force_sha256)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002333{
Hai Shalom021b0b52019-04-10 11:17:58 -07002334 const u8 *z = NULL;
Hai Shalom60840252021-02-19 19:02:11 -08002335 size_t z_len = 0, kdk_len;
Hai Shalomfdcde762020-04-02 11:19:20 -07002336 int akmp;
Sunil Ravi89eba102022-09-13 21:04:37 -07002337 int ret;
Hai Shalom021b0b52019-04-10 11:17:58 -07002338
Hai Shalom60840252021-02-19 19:02:11 -08002339 if (sm->wpa_auth->conf.force_kdk_derivation ||
2340 (sm->wpa_auth->conf.secure_ltf &&
Hai Shaloma20dcd72022-02-04 13:43:00 -08002341 ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
Hai Shalom60840252021-02-19 19:02:11 -08002342 kdk_len = WPA_KDK_MAX_LEN;
2343 else
2344 kdk_len = 0;
2345
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002346#ifdef CONFIG_IEEE80211R_AP
Hai Shalom81f62d82019-07-22 12:10:00 -07002347 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
2348 if (sm->ft_completed) {
2349 u8 ptk_name[WPA_PMK_NAME_LEN];
2350
Sunil Ravi89eba102022-09-13 21:04:37 -07002351 ret = wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->pmk_r1_len,
2352 sm->SNonce, sm->ANonce,
2353 sm->addr, sm->wpa_auth->addr,
2354 sm->pmk_r1_name, ptk,
2355 ptk_name, sm->wpa_key_mgmt,
2356 sm->pairwise, kdk_len);
2357 } else {
2358 ret = wpa_auth_derive_ptk_ft(sm, ptk);
Hai Shalom81f62d82019-07-22 12:10:00 -07002359 }
Sunil Ravi89eba102022-09-13 21:04:37 -07002360 if (ret) {
2361 wpa_printf(MSG_ERROR, "FT: PTK derivation failed");
2362 return ret;
2363 }
2364
2365#ifdef CONFIG_PASN
2366 if (sm->wpa_auth->conf.secure_ltf &&
2367 ieee802_11_rsnx_capab(sm->rsnxe,
2368 WLAN_RSNX_CAPAB_SECURE_LTF)) {
2369 ret = wpa_ltf_keyseed(ptk, sm->wpa_key_mgmt,
2370 sm->pairwise);
2371 if (ret) {
2372 wpa_printf(MSG_ERROR,
2373 "FT: LTF keyseed derivation failed");
2374 }
2375 }
2376#endif /* CONFIG_PASN */
2377 return ret;
Hai Shalom81f62d82019-07-22 12:10:00 -07002378 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002379#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002380
Hai Shalom021b0b52019-04-10 11:17:58 -07002381#ifdef CONFIG_DPP2
2382 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP && sm->dpp_z) {
2383 z = wpabuf_head(sm->dpp_z);
2384 z_len = wpabuf_len(sm->dpp_z);
2385 }
2386#endif /* CONFIG_DPP2 */
2387
Hai Shalomfdcde762020-04-02 11:19:20 -07002388 akmp = sm->wpa_key_mgmt;
2389 if (force_sha256)
2390 akmp |= WPA_KEY_MGMT_PSK_SHA256;
Sunil Ravi89eba102022-09-13 21:04:37 -07002391 ret = wpa_pmk_to_ptk(pmk, pmk_len, "Pairwise key expansion",
2392 sm->wpa_auth->addr, sm->addr, sm->ANonce,
2393 snonce, ptk, akmp, sm->pairwise, z, z_len,
2394 kdk_len);
2395 if (ret) {
2396 wpa_printf(MSG_DEBUG,
2397 "WPA: PTK derivation failed");
2398 return ret;
2399 }
2400
2401#ifdef CONFIG_PASN
2402 if (sm->wpa_auth->conf.secure_ltf &&
2403 ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)) {
2404 ret = wpa_ltf_keyseed(ptk, sm->wpa_key_mgmt, sm->pairwise);
2405 if (ret) {
2406 wpa_printf(MSG_DEBUG,
2407 "WPA: LTF keyseed derivation failed");
2408 }
2409 }
2410#endif /* CONFIG_PASN */
2411 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002412}
2413
2414
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002415#ifdef CONFIG_FILS
2416
2417int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002418 size_t pmk_len, const u8 *snonce, const u8 *anonce,
2419 const u8 *dhss, size_t dhss_len,
2420 struct wpabuf *g_sta, struct wpabuf *g_ap)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002421{
2422 u8 ick[FILS_ICK_MAX_LEN];
2423 size_t ick_len;
2424 int res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002425 u8 fils_ft[FILS_FT_MAX_LEN];
Hai Shalom60840252021-02-19 19:02:11 -08002426 size_t fils_ft_len = 0, kdk_len;
2427
2428 if (sm->wpa_auth->conf.force_kdk_derivation ||
2429 (sm->wpa_auth->conf.secure_ltf &&
Hai Shaloma20dcd72022-02-04 13:43:00 -08002430 ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
Hai Shalom60840252021-02-19 19:02:11 -08002431 kdk_len = WPA_KDK_MAX_LEN;
2432 else
2433 kdk_len = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002434
2435 res = fils_pmk_to_ptk(pmk, pmk_len, sm->addr, sm->wpa_auth->addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002436 snonce, anonce, dhss, dhss_len,
2437 &sm->PTK, ick, &ick_len,
2438 sm->wpa_key_mgmt, sm->pairwise,
Hai Shalom60840252021-02-19 19:02:11 -08002439 fils_ft, &fils_ft_len, kdk_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002440 if (res < 0)
2441 return res;
Sunil Ravi89eba102022-09-13 21:04:37 -07002442
2443#ifdef CONFIG_PASN
2444 if (sm->wpa_auth->conf.secure_ltf &&
2445 ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)) {
2446 res = wpa_ltf_keyseed(&sm->PTK, sm->wpa_key_mgmt, sm->pairwise);
2447 if (res) {
2448 wpa_printf(MSG_ERROR,
2449 "FILS: LTF keyseed derivation failed");
2450 return res;
2451 }
2452 }
2453#endif /* CONFIG_PASN */
2454
Hai Shalome21d4e82020-04-29 16:34:06 -07002455 sm->PTK_valid = true;
2456 sm->tk_already_set = false;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002457
2458#ifdef CONFIG_IEEE80211R_AP
2459 if (fils_ft_len) {
2460 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
2461 struct wpa_auth_config *conf = &wpa_auth->conf;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002462 u8 pmk_r0[PMK_LEN_MAX], pmk_r0_name[WPA_PMK_NAME_LEN];
2463 int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002464
2465 if (wpa_derive_pmk_r0(fils_ft, fils_ft_len,
2466 conf->ssid, conf->ssid_len,
2467 conf->mobility_domain,
2468 conf->r0_key_holder,
2469 conf->r0_key_holder_len,
Roshan Pius3a1667e2018-07-03 15:17:14 -07002470 sm->addr, pmk_r0, pmk_r0_name,
2471 use_sha384) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002472 return -1;
2473
Roshan Pius3a1667e2018-07-03 15:17:14 -07002474 wpa_ft_store_pmk_fils(sm, pmk_r0, pmk_r0_name);
Hai Shalom81f62d82019-07-22 12:10:00 -07002475 forced_memzero(fils_ft, sizeof(fils_ft));
Hai Shalom021b0b52019-04-10 11:17:58 -07002476
2477 res = wpa_derive_pmk_r1_name(pmk_r0_name, conf->r1_key_holder,
2478 sm->addr, sm->pmk_r1_name,
2479 use_sha384);
Hai Shalom81f62d82019-07-22 12:10:00 -07002480 forced_memzero(pmk_r0, PMK_LEN_MAX);
Hai Shalom021b0b52019-04-10 11:17:58 -07002481 if (res < 0)
2482 return -1;
2483 wpa_hexdump(MSG_DEBUG, "FILS+FT: PMKR1Name", sm->pmk_r1_name,
2484 WPA_PMK_NAME_LEN);
2485 sm->pmk_r1_name_valid = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002486 }
2487#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002488
2489 res = fils_key_auth_sk(ick, ick_len, snonce, anonce,
2490 sm->addr, sm->wpa_auth->addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002491 g_sta ? wpabuf_head(g_sta) : NULL,
2492 g_sta ? wpabuf_len(g_sta) : 0,
2493 g_ap ? wpabuf_head(g_ap) : NULL,
2494 g_ap ? wpabuf_len(g_ap) : 0,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002495 sm->wpa_key_mgmt, sm->fils_key_auth_sta,
2496 sm->fils_key_auth_ap,
2497 &sm->fils_key_auth_len);
Hai Shalom81f62d82019-07-22 12:10:00 -07002498 forced_memzero(ick, sizeof(ick));
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002499
2500 /* Store nonces for (Re)Association Request/Response frame processing */
2501 os_memcpy(sm->SNonce, snonce, FILS_NONCE_LEN);
2502 os_memcpy(sm->ANonce, anonce, FILS_NONCE_LEN);
2503
2504 return res;
2505}
2506
2507
2508static int wpa_aead_decrypt(struct wpa_state_machine *sm, struct wpa_ptk *ptk,
2509 u8 *buf, size_t buf_len, u16 *_key_data_len)
2510{
2511 struct ieee802_1x_hdr *hdr;
2512 struct wpa_eapol_key *key;
2513 u8 *pos;
2514 u16 key_data_len;
2515 u8 *tmp;
2516 const u8 *aad[1];
2517 size_t aad_len[1];
2518
2519 hdr = (struct ieee802_1x_hdr *) buf;
2520 key = (struct wpa_eapol_key *) (hdr + 1);
2521 pos = (u8 *) (key + 1);
2522 key_data_len = WPA_GET_BE16(pos);
2523 if (key_data_len < AES_BLOCK_SIZE ||
2524 key_data_len > buf_len - sizeof(*hdr) - sizeof(*key) - 2) {
2525 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO,
2526 "No room for AES-SIV data in the frame");
2527 return -1;
2528 }
2529 pos += 2; /* Pointing at the Encrypted Key Data field */
2530
2531 tmp = os_malloc(key_data_len);
2532 if (!tmp)
2533 return -1;
2534
2535 /* AES-SIV AAD from EAPOL protocol version field (inclusive) to
2536 * to Key Data (exclusive). */
2537 aad[0] = buf;
2538 aad_len[0] = pos - buf;
2539 if (aes_siv_decrypt(ptk->kek, ptk->kek_len, pos, key_data_len,
2540 1, aad, aad_len, tmp) < 0) {
2541 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO,
2542 "Invalid AES-SIV data in the frame");
2543 bin_clear_free(tmp, key_data_len);
2544 return -1;
2545 }
2546
2547 /* AEAD decryption and validation completed successfully */
2548 key_data_len -= AES_BLOCK_SIZE;
2549 wpa_hexdump_key(MSG_DEBUG, "WPA: Decrypted Key Data",
2550 tmp, key_data_len);
2551
2552 /* Replace Key Data field with the decrypted version */
2553 os_memcpy(pos, tmp, key_data_len);
2554 pos -= 2; /* Key Data Length field */
2555 WPA_PUT_BE16(pos, key_data_len);
2556 bin_clear_free(tmp, key_data_len);
2557 if (_key_data_len)
2558 *_key_data_len = key_data_len;
2559 return 0;
2560}
2561
2562
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002563const u8 * wpa_fils_validate_fils_session(struct wpa_state_machine *sm,
2564 const u8 *ies, size_t ies_len,
2565 const u8 *fils_session)
2566{
2567 const u8 *ie, *end;
2568 const u8 *session = NULL;
2569
2570 if (!wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
2571 wpa_printf(MSG_DEBUG,
2572 "FILS: Not a FILS AKM - reject association");
2573 return NULL;
2574 }
2575
2576 /* Verify Session element */
2577 ie = ies;
2578 end = ((const u8 *) ie) + ies_len;
2579 while (ie + 1 < end) {
2580 if (ie + 2 + ie[1] > end)
2581 break;
2582 if (ie[0] == WLAN_EID_EXTENSION &&
2583 ie[1] >= 1 + FILS_SESSION_LEN &&
2584 ie[2] == WLAN_EID_EXT_FILS_SESSION) {
2585 session = ie;
2586 break;
2587 }
2588 ie += 2 + ie[1];
2589 }
2590
2591 if (!session) {
2592 wpa_printf(MSG_DEBUG,
2593 "FILS: %s: Could not find FILS Session element in Assoc Req - reject",
2594 __func__);
2595 return NULL;
2596 }
2597
2598 if (!fils_session) {
2599 wpa_printf(MSG_DEBUG,
2600 "FILS: %s: Could not find FILS Session element in STA entry - reject",
2601 __func__);
2602 return NULL;
2603 }
2604
2605 if (os_memcmp(fils_session, session + 3, FILS_SESSION_LEN) != 0) {
2606 wpa_printf(MSG_DEBUG, "FILS: Session mismatch");
2607 wpa_hexdump(MSG_DEBUG, "FILS: Expected FILS Session",
2608 fils_session, FILS_SESSION_LEN);
2609 wpa_hexdump(MSG_DEBUG, "FILS: Received FILS Session",
2610 session + 3, FILS_SESSION_LEN);
2611 return NULL;
2612 }
2613 return session;
2614}
2615
2616
2617int wpa_fils_validate_key_confirm(struct wpa_state_machine *sm, const u8 *ies,
2618 size_t ies_len)
2619{
2620 struct ieee802_11_elems elems;
2621
2622 if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed) {
2623 wpa_printf(MSG_DEBUG,
2624 "FILS: Failed to parse decrypted elements");
2625 return -1;
2626 }
2627
2628 if (!elems.fils_session) {
2629 wpa_printf(MSG_DEBUG, "FILS: No FILS Session element");
2630 return -1;
2631 }
2632
2633 if (!elems.fils_key_confirm) {
2634 wpa_printf(MSG_DEBUG, "FILS: No FILS Key Confirm element");
2635 return -1;
2636 }
2637
2638 if (elems.fils_key_confirm_len != sm->fils_key_auth_len) {
2639 wpa_printf(MSG_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07002640 "FILS: Unexpected Key-Auth length %d (expected %zu)",
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002641 elems.fils_key_confirm_len,
Hai Shalomfdcde762020-04-02 11:19:20 -07002642 sm->fils_key_auth_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002643 return -1;
2644 }
2645
2646 if (os_memcmp(elems.fils_key_confirm, sm->fils_key_auth_sta,
2647 sm->fils_key_auth_len) != 0) {
2648 wpa_printf(MSG_DEBUG, "FILS: Key-Auth mismatch");
2649 wpa_hexdump(MSG_DEBUG, "FILS: Received Key-Auth",
2650 elems.fils_key_confirm, elems.fils_key_confirm_len);
2651 wpa_hexdump(MSG_DEBUG, "FILS: Expected Key-Auth",
2652 sm->fils_key_auth_sta, sm->fils_key_auth_len);
2653 return -1;
2654 }
2655
2656 return 0;
2657}
2658
2659
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002660int fils_decrypt_assoc(struct wpa_state_machine *sm, const u8 *fils_session,
2661 const struct ieee80211_mgmt *mgmt, size_t frame_len,
2662 u8 *pos, size_t left)
2663{
2664 u16 fc, stype;
2665 const u8 *end, *ie_start, *ie, *session, *crypt;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002666 const u8 *aad[5];
2667 size_t aad_len[5];
2668
2669 if (!sm || !sm->PTK_valid) {
2670 wpa_printf(MSG_DEBUG,
2671 "FILS: No KEK to decrypt Assocication Request frame");
2672 return -1;
2673 }
2674
2675 if (!wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
2676 wpa_printf(MSG_DEBUG,
2677 "FILS: Not a FILS AKM - reject association");
2678 return -1;
2679 }
2680
2681 end = ((const u8 *) mgmt) + frame_len;
2682 fc = le_to_host16(mgmt->frame_control);
2683 stype = WLAN_FC_GET_STYPE(fc);
2684 if (stype == WLAN_FC_STYPE_REASSOC_REQ)
2685 ie_start = mgmt->u.reassoc_req.variable;
2686 else
2687 ie_start = mgmt->u.assoc_req.variable;
2688 ie = ie_start;
2689
2690 /*
2691 * Find FILS Session element which is the last unencrypted element in
2692 * the frame.
2693 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002694 session = wpa_fils_validate_fils_session(sm, ie, end - ie,
2695 fils_session);
2696 if (!session) {
2697 wpa_printf(MSG_DEBUG, "FILS: Session validation failed");
2698 return -1;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002699 }
2700
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002701 crypt = session + 2 + session[1];
2702
2703 if (end - crypt < AES_BLOCK_SIZE) {
2704 wpa_printf(MSG_DEBUG,
2705 "FILS: Too short frame to include AES-SIV data");
2706 return -1;
2707 }
2708
2709 /* AES-SIV AAD vectors */
2710
2711 /* The STA's MAC address */
2712 aad[0] = mgmt->sa;
2713 aad_len[0] = ETH_ALEN;
2714 /* The AP's BSSID */
2715 aad[1] = mgmt->da;
2716 aad_len[1] = ETH_ALEN;
2717 /* The STA's nonce */
2718 aad[2] = sm->SNonce;
2719 aad_len[2] = FILS_NONCE_LEN;
2720 /* The AP's nonce */
2721 aad[3] = sm->ANonce;
2722 aad_len[3] = FILS_NONCE_LEN;
2723 /*
2724 * The (Re)Association Request frame from the Capability Information
2725 * field to the FILS Session element (both inclusive).
2726 */
2727 aad[4] = (const u8 *) &mgmt->u.assoc_req.capab_info;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002728 aad_len[4] = crypt - aad[4];
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002729
2730 if (aes_siv_decrypt(sm->PTK.kek, sm->PTK.kek_len, crypt, end - crypt,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002731 5, aad, aad_len, pos + (crypt - ie_start)) < 0) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002732 wpa_printf(MSG_DEBUG,
2733 "FILS: Invalid AES-SIV data in the frame");
2734 return -1;
2735 }
2736 wpa_hexdump(MSG_DEBUG, "FILS: Decrypted Association Request elements",
2737 pos, left - AES_BLOCK_SIZE);
2738
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002739 if (wpa_fils_validate_key_confirm(sm, pos, left - AES_BLOCK_SIZE) < 0) {
2740 wpa_printf(MSG_DEBUG, "FILS: Key Confirm validation failed");
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002741 return -1;
2742 }
2743
2744 return left - AES_BLOCK_SIZE;
2745}
2746
2747
2748int fils_encrypt_assoc(struct wpa_state_machine *sm, u8 *buf,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002749 size_t current_len, size_t max_len,
2750 const struct wpabuf *hlp)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002751{
2752 u8 *end = buf + max_len;
2753 u8 *pos = buf + current_len;
2754 struct ieee80211_mgmt *mgmt;
2755 struct wpabuf *plain;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002756 const u8 *aad[5];
2757 size_t aad_len[5];
2758
2759 if (!sm || !sm->PTK_valid)
2760 return -1;
2761
2762 wpa_hexdump(MSG_DEBUG,
2763 "FILS: Association Response frame before FILS processing",
2764 buf, current_len);
2765
2766 mgmt = (struct ieee80211_mgmt *) buf;
2767
2768 /* AES-SIV AAD vectors */
2769
2770 /* The AP's BSSID */
2771 aad[0] = mgmt->sa;
2772 aad_len[0] = ETH_ALEN;
2773 /* The STA's MAC address */
2774 aad[1] = mgmt->da;
2775 aad_len[1] = ETH_ALEN;
2776 /* The AP's nonce */
2777 aad[2] = sm->ANonce;
2778 aad_len[2] = FILS_NONCE_LEN;
2779 /* The STA's nonce */
2780 aad[3] = sm->SNonce;
2781 aad_len[3] = FILS_NONCE_LEN;
2782 /*
2783 * The (Re)Association Response frame from the Capability Information
2784 * field (the same offset in both Association and Reassociation
2785 * Response frames) to the FILS Session element (both inclusive).
2786 */
2787 aad[4] = (const u8 *) &mgmt->u.assoc_resp.capab_info;
2788 aad_len[4] = pos - aad[4];
2789
2790 /* The following elements will be encrypted with AES-SIV */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002791 plain = fils_prepare_plainbuf(sm, hlp);
2792 if (!plain) {
2793 wpa_printf(MSG_DEBUG, "FILS: Plain buffer prep failed");
2794 return -1;
2795 }
2796
2797 if (pos + wpabuf_len(plain) + AES_BLOCK_SIZE > end) {
2798 wpa_printf(MSG_DEBUG,
2799 "FILS: Not enough room for FILS elements");
Hai Shalom81f62d82019-07-22 12:10:00 -07002800 wpabuf_clear_free(plain);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002801 return -1;
2802 }
2803
2804 wpa_hexdump_buf_key(MSG_DEBUG, "FILS: Association Response plaintext",
2805 plain);
2806
2807 if (aes_siv_encrypt(sm->PTK.kek, sm->PTK.kek_len,
2808 wpabuf_head(plain), wpabuf_len(plain),
2809 5, aad, aad_len, pos) < 0) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002810 wpabuf_clear_free(plain);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002811 return -1;
2812 }
2813
2814 wpa_hexdump(MSG_DEBUG,
2815 "FILS: Encrypted Association Response elements",
2816 pos, AES_BLOCK_SIZE + wpabuf_len(plain));
2817 current_len += wpabuf_len(plain) + AES_BLOCK_SIZE;
Hai Shalom81f62d82019-07-22 12:10:00 -07002818 wpabuf_clear_free(plain);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002819
2820 sm->fils_completed = 1;
2821
2822 return current_len;
2823}
2824
2825
2826static struct wpabuf * fils_prepare_plainbuf(struct wpa_state_machine *sm,
2827 const struct wpabuf *hlp)
2828{
2829 struct wpabuf *plain;
2830 u8 *len, *tmp, *tmp2;
2831 u8 hdr[2];
Hai Shaloma20dcd72022-02-04 13:43:00 -08002832 u8 *gtk, stub_gtk[32];
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002833 size_t gtk_len;
2834 struct wpa_group *gsm;
Hai Shalomfdcde762020-04-02 11:19:20 -07002835 size_t plain_len;
2836 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002837
Hai Shalomfdcde762020-04-02 11:19:20 -07002838 plain_len = 1000 + ieee80211w_kde_len(sm);
2839 if (conf->transition_disable)
2840 plain_len += 2 + RSN_SELECTOR_LEN + 1;
2841 plain = wpabuf_alloc(plain_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002842 if (!plain)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002843 return NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002844
2845 /* TODO: FILS Public Key */
2846
2847 /* FILS Key Confirmation */
2848 wpabuf_put_u8(plain, WLAN_EID_EXTENSION); /* Element ID */
2849 wpabuf_put_u8(plain, 1 + sm->fils_key_auth_len); /* Length */
2850 /* Element ID Extension */
2851 wpabuf_put_u8(plain, WLAN_EID_EXT_FILS_KEY_CONFIRM);
2852 wpabuf_put_data(plain, sm->fils_key_auth_ap, sm->fils_key_auth_len);
2853
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002854 /* FILS HLP Container */
2855 if (hlp)
2856 wpabuf_put_buf(plain, hlp);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002857
2858 /* TODO: FILS IP Address Assignment */
2859
2860 /* Key Delivery */
2861 gsm = sm->group;
2862 wpabuf_put_u8(plain, WLAN_EID_EXTENSION); /* Element ID */
2863 len = wpabuf_put(plain, 1);
2864 wpabuf_put_u8(plain, WLAN_EID_EXT_KEY_DELIVERY);
2865 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN,
2866 wpabuf_put(plain, WPA_KEY_RSC_LEN));
2867 /* GTK KDE */
2868 gtk = gsm->GTK[gsm->GN - 1];
2869 gtk_len = gsm->GTK_len;
Hai Shalomfdcde762020-04-02 11:19:20 -07002870 if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002871 /*
2872 * Provide unique random GTK to each STA to prevent use
2873 * of GTK in the BSS.
2874 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08002875 if (random_get_bytes(stub_gtk, gtk_len) < 0) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002876 wpabuf_clear_free(plain);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002877 return NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002878 }
Hai Shaloma20dcd72022-02-04 13:43:00 -08002879 gtk = stub_gtk;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002880 }
2881 hdr[0] = gsm->GN & 0x03;
2882 hdr[1] = 0;
2883 tmp = wpabuf_put(plain, 0);
2884 tmp2 = wpa_add_kde(tmp, RSN_KEY_DATA_GROUPKEY, hdr, 2,
2885 gtk, gtk_len);
2886 wpabuf_put(plain, tmp2 - tmp);
2887
Hai Shalomfdcde762020-04-02 11:19:20 -07002888 /* IGTK KDE and BIGTK KDE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002889 tmp = wpabuf_put(plain, 0);
2890 tmp2 = ieee80211w_kde_add(sm, tmp);
2891 wpabuf_put(plain, tmp2 - tmp);
2892
Hai Shalomfdcde762020-04-02 11:19:20 -07002893 if (conf->transition_disable) {
2894 tmp = wpabuf_put(plain, 0);
2895 tmp2 = wpa_add_kde(tmp, WFA_KEY_DATA_TRANSITION_DISABLE,
2896 &conf->transition_disable, 1, NULL, 0);
2897 wpabuf_put(plain, tmp2 - tmp);
2898 }
2899
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002900 *len = (u8 *) wpabuf_put(plain, 0) - len - 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08002901
2902#ifdef CONFIG_OCV
2903 if (wpa_auth_uses_ocv(sm)) {
2904 struct wpa_channel_info ci;
2905 u8 *pos;
2906
2907 if (wpa_channel_info(sm->wpa_auth, &ci) != 0) {
2908 wpa_printf(MSG_WARNING,
2909 "FILS: Failed to get channel info for OCI element");
Hai Shalom81f62d82019-07-22 12:10:00 -07002910 wpabuf_clear_free(plain);
Hai Shalom74f70d42019-02-11 14:42:39 -08002911 return NULL;
2912 }
Hai Shalom899fcc72020-10-19 14:38:18 -07002913#ifdef CONFIG_TESTING_OPTIONS
2914 if (conf->oci_freq_override_fils_assoc) {
2915 wpa_printf(MSG_INFO,
2916 "TEST: Override OCI frequency %d -> %u MHz",
2917 ci.frequency,
2918 conf->oci_freq_override_fils_assoc);
2919 ci.frequency = conf->oci_freq_override_fils_assoc;
2920 }
2921#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom74f70d42019-02-11 14:42:39 -08002922
2923 pos = wpabuf_put(plain, OCV_OCI_EXTENDED_LEN);
2924 if (ocv_insert_extended_oci(&ci, pos) < 0) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002925 wpabuf_clear_free(plain);
Hai Shalom74f70d42019-02-11 14:42:39 -08002926 return NULL;
2927 }
2928 }
2929#endif /* CONFIG_OCV */
2930
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002931 return plain;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002932}
2933
2934
2935int fils_set_tk(struct wpa_state_machine *sm)
2936{
2937 enum wpa_alg alg;
2938 int klen;
2939
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002940 if (!sm || !sm->PTK_valid) {
2941 wpa_printf(MSG_DEBUG, "FILS: No valid PTK available to set TK");
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002942 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002943 }
2944 if (sm->tk_already_set) {
2945 wpa_printf(MSG_DEBUG, "FILS: TK already set to the driver");
2946 return -1;
2947 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002948
2949 alg = wpa_cipher_to_alg(sm->pairwise);
2950 klen = wpa_cipher_key_len(sm->pairwise);
2951
2952 wpa_printf(MSG_DEBUG, "FILS: Configure TK to the driver");
2953 if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0,
Hai Shalomfdcde762020-04-02 11:19:20 -07002954 sm->PTK.tk, klen, KEY_FLAG_PAIRWISE_RX_TX)) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002955 wpa_printf(MSG_DEBUG, "FILS: Failed to set TK to the driver");
2956 return -1;
2957 }
Sunil Ravi89eba102022-09-13 21:04:37 -07002958
2959#ifdef CONFIG_PASN
2960 if (sm->wpa_auth->conf.secure_ltf &&
2961 ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF) &&
2962 wpa_auth_set_ltf_keyseed(sm->wpa_auth, sm->addr,
2963 sm->PTK.ltf_keyseed,
2964 sm->PTK.ltf_keyseed_len)) {
2965 wpa_printf(MSG_ERROR,
2966 "FILS: Failed to set LTF keyseed to driver");
2967 return -1;
2968 }
2969#endif /* CONFIG_PASN */
2970
Sunil8cd6f4d2022-06-28 18:40:46 +00002971 sm->pairwise_set = true;
Hai Shalome21d4e82020-04-29 16:34:06 -07002972 sm->tk_already_set = true;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002973
Hai Shalom60840252021-02-19 19:02:11 -08002974 wpa_auth_store_ptksa(sm->wpa_auth, sm->addr, sm->pairwise,
2975 dot11RSNAConfigPMKLifetime, &sm->PTK);
2976
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002977 return 0;
2978}
2979
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002980
2981u8 * hostapd_eid_assoc_fils_session(struct wpa_state_machine *sm, u8 *buf,
2982 const u8 *fils_session, struct wpabuf *hlp)
2983{
2984 struct wpabuf *plain;
2985 u8 *pos = buf;
2986
2987 /* FILS Session */
2988 *pos++ = WLAN_EID_EXTENSION; /* Element ID */
2989 *pos++ = 1 + FILS_SESSION_LEN; /* Length */
2990 *pos++ = WLAN_EID_EXT_FILS_SESSION; /* Element ID Extension */
2991 os_memcpy(pos, fils_session, FILS_SESSION_LEN);
2992 pos += FILS_SESSION_LEN;
2993
2994 plain = fils_prepare_plainbuf(sm, hlp);
2995 if (!plain) {
2996 wpa_printf(MSG_DEBUG, "FILS: Plain buffer prep failed");
2997 return NULL;
2998 }
2999
3000 os_memcpy(pos, wpabuf_head(plain), wpabuf_len(plain));
3001 pos += wpabuf_len(plain);
3002
Hai Shalomfdcde762020-04-02 11:19:20 -07003003 wpa_printf(MSG_DEBUG, "%s: plain buf_len: %zu", __func__,
3004 wpabuf_len(plain));
Hai Shalom81f62d82019-07-22 12:10:00 -07003005 wpabuf_clear_free(plain);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003006 sm->fils_completed = 1;
3007 return pos;
3008}
3009
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003010#endif /* CONFIG_FILS */
3011
3012
Hai Shalom74f70d42019-02-11 14:42:39 -08003013#ifdef CONFIG_OCV
3014int get_sta_tx_parameters(struct wpa_state_machine *sm, int ap_max_chanwidth,
3015 int ap_seg1_idx, int *bandwidth, int *seg1_idx)
3016{
3017 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
3018
3019 if (!wpa_auth->cb->get_sta_tx_params)
3020 return -1;
3021 return wpa_auth->cb->get_sta_tx_params(wpa_auth->cb_ctx, sm->addr,
3022 ap_max_chanwidth, ap_seg1_idx,
3023 bandwidth, seg1_idx);
3024}
3025#endif /* CONFIG_OCV */
3026
3027
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003028SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
3029{
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003030 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003031 struct wpa_ptk PTK;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07003032 int ok = 0, psk_found = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003033 const u8 *pmk = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003034 size_t pmk_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003035 int ft;
3036 const u8 *eapol_key_ie, *key_data, *mic;
3037 u16 key_data_length;
3038 size_t mic_len, eapol_key_ie_len;
3039 struct ieee802_1x_hdr *hdr;
3040 struct wpa_eapol_key *key;
3041 struct wpa_eapol_ie_parse kde;
Hai Shalom021b0b52019-04-10 11:17:58 -07003042 int vlan_id = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07003043 int owe_ptk_workaround = !!wpa_auth->conf.owe_ptk_workaround;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003044
3045 SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07003046 sm->EAPOLKeyReceived = false;
3047 sm->update_snonce = false;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003048 os_memset(&PTK, 0, sizeof(PTK));
3049
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003050 mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003051
3052 /* WPA with IEEE 802.1X: use the derived PMK from EAP
3053 * WPA-PSK: iterate through possible PSKs and select the one matching
3054 * the packet */
3055 for (;;) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003056 if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
3057 !wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07003058 pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr,
Hai Shalom021b0b52019-04-10 11:17:58 -07003059 sm->p2p_dev_addr, pmk, &pmk_len,
3060 &vlan_id);
Hai Shalomfdcde762020-04-02 11:19:20 -07003061 if (!pmk)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003062 break;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07003063 psk_found = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003064#ifdef CONFIG_IEEE80211R_AP
3065 if (wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) {
3066 os_memcpy(sm->xxkey, pmk, pmk_len);
3067 sm->xxkey_len = pmk_len;
3068 }
3069#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003070 } else {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003071 pmk = sm->PMK;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003072 pmk_len = sm->pmk_len;
3073 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003074
Hai Shalom81f62d82019-07-22 12:10:00 -07003075 if ((!pmk || !pmk_len) && sm->pmksa) {
3076 wpa_printf(MSG_DEBUG, "WPA: Use PMK from PMKSA cache");
3077 pmk = sm->pmksa->pmk;
3078 pmk_len = sm->pmksa->pmk_len;
3079 }
3080
Hai Shalomfdcde762020-04-02 11:19:20 -07003081 if (wpa_derive_ptk(sm, sm->SNonce, pmk, pmk_len, &PTK,
3082 owe_ptk_workaround == 2) < 0)
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003083 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003084
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003085 if (mic_len &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003086 wpa_verify_key_mic(sm->wpa_key_mgmt, pmk_len, &PTK,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003087 sm->last_rx_eapol_key,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003088 sm->last_rx_eapol_key_len) == 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07003089 if (sm->PMK != pmk) {
3090 os_memcpy(sm->PMK, pmk, pmk_len);
3091 sm->pmk_len = pmk_len;
3092 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003093 ok = 1;
3094 break;
3095 }
3096
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003097#ifdef CONFIG_FILS
3098 if (!mic_len &&
3099 wpa_aead_decrypt(sm, &PTK, sm->last_rx_eapol_key,
3100 sm->last_rx_eapol_key_len, NULL) == 0) {
3101 ok = 1;
3102 break;
3103 }
3104#endif /* CONFIG_FILS */
3105
Hai Shalomfdcde762020-04-02 11:19:20 -07003106#ifdef CONFIG_OWE
3107 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE && pmk_len > 32 &&
3108 owe_ptk_workaround == 1) {
3109 wpa_printf(MSG_DEBUG,
3110 "OWE: Try PTK derivation workaround with SHA256");
3111 owe_ptk_workaround = 2;
3112 continue;
3113 }
3114#endif /* CONFIG_OWE */
3115
Roshan Pius3a1667e2018-07-03 15:17:14 -07003116 if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
3117 wpa_key_mgmt_sae(sm->wpa_key_mgmt))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003118 break;
3119 }
3120
Sunil Ravia04bd252022-05-02 22:54:18 -07003121 if (!ok && wpa_key_mgmt_wpa_psk_no_sae(sm->wpa_key_mgmt) &&
3122 wpa_auth->conf.radius_psk && wpa_auth->cb->request_radius_psk &&
3123 !sm->waiting_radius_psk) {
3124 wpa_printf(MSG_DEBUG, "No PSK available - ask RADIUS server");
3125 wpa_auth->cb->request_radius_psk(wpa_auth->cb_ctx, sm->addr,
3126 sm->wpa_key_mgmt,
3127 sm->ANonce,
3128 sm->last_rx_eapol_key,
3129 sm->last_rx_eapol_key_len);
3130 sm->waiting_radius_psk = 1;
3131 return;
3132 }
3133
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003134 if (!ok) {
3135 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
3136 "invalid MIC in msg 2/4 of 4-Way Handshake");
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07003137 if (psk_found)
3138 wpa_auth_psk_failure_report(sm->wpa_auth, sm->addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003139 return;
3140 }
3141
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003142 /*
3143 * Note: last_rx_eapol_key length fields have already been validated in
3144 * wpa_receive().
3145 */
3146 hdr = (struct ieee802_1x_hdr *) sm->last_rx_eapol_key;
3147 key = (struct wpa_eapol_key *) (hdr + 1);
3148 mic = (u8 *) (key + 1);
3149 key_data = mic + mic_len + 2;
3150 key_data_length = WPA_GET_BE16(mic + mic_len);
3151 if (key_data_length > sm->last_rx_eapol_key_len - sizeof(*hdr) -
3152 sizeof(*key) - mic_len - 2)
3153 return;
3154
3155 if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) {
3156 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
3157 "received EAPOL-Key msg 2/4 with invalid Key Data contents");
3158 return;
3159 }
3160 if (kde.rsn_ie) {
3161 eapol_key_ie = kde.rsn_ie;
3162 eapol_key_ie_len = kde.rsn_ie_len;
3163 } else if (kde.osen) {
3164 eapol_key_ie = kde.osen;
3165 eapol_key_ie_len = kde.osen_len;
3166 } else {
3167 eapol_key_ie = kde.wpa_ie;
3168 eapol_key_ie_len = kde.wpa_ie_len;
3169 }
3170 ft = sm->wpa == WPA_VERSION_WPA2 && wpa_key_mgmt_ft(sm->wpa_key_mgmt);
Hai Shalomfdcde762020-04-02 11:19:20 -07003171 if (!sm->wpa_ie ||
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003172 wpa_compare_rsn_ie(ft, sm->wpa_ie, sm->wpa_ie_len,
3173 eapol_key_ie, eapol_key_ie_len)) {
3174 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
3175 "WPA IE from (Re)AssocReq did not match with msg 2/4");
3176 if (sm->wpa_ie) {
3177 wpa_hexdump(MSG_DEBUG, "WPA IE in AssocReq",
3178 sm->wpa_ie, sm->wpa_ie_len);
3179 }
3180 wpa_hexdump(MSG_DEBUG, "WPA IE in msg 2/4",
3181 eapol_key_ie, eapol_key_ie_len);
3182 /* MLME-DEAUTHENTICATE.request */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003183 wpa_sta_disconnect(wpa_auth, sm->addr,
3184 WLAN_REASON_PREV_AUTH_NOT_VALID);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003185 return;
3186 }
Hai Shalomc3565922019-10-28 11:58:20 -07003187 if ((!sm->rsnxe && kde.rsnxe) ||
3188 (sm->rsnxe && !kde.rsnxe) ||
3189 (sm->rsnxe && kde.rsnxe &&
3190 (sm->rsnxe_len != kde.rsnxe_len ||
3191 os_memcmp(sm->rsnxe, kde.rsnxe, sm->rsnxe_len) != 0))) {
3192 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
3193 "RSNXE from (Re)AssocReq did not match the one in EAPOL-Key msg 2/4");
3194 wpa_hexdump(MSG_DEBUG, "RSNXE in AssocReq",
3195 sm->rsnxe, sm->rsnxe_len);
3196 wpa_hexdump(MSG_DEBUG, "RSNXE in EAPOL-Key msg 2/4",
3197 kde.rsnxe, kde.rsnxe_len);
3198 /* MLME-DEAUTHENTICATE.request */
3199 wpa_sta_disconnect(wpa_auth, sm->addr,
3200 WLAN_REASON_PREV_AUTH_NOT_VALID);
3201 return;
3202 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003203#ifdef CONFIG_OCV
3204 if (wpa_auth_uses_ocv(sm)) {
3205 struct wpa_channel_info ci;
3206 int tx_chanwidth;
3207 int tx_seg1_idx;
Hai Shalom899fcc72020-10-19 14:38:18 -07003208 enum oci_verify_result res;
Hai Shalom74f70d42019-02-11 14:42:39 -08003209
3210 if (wpa_channel_info(wpa_auth, &ci) != 0) {
3211 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
3212 "Failed to get channel info to validate received OCI in EAPOL-Key 2/4");
3213 return;
3214 }
3215
3216 if (get_sta_tx_parameters(sm,
3217 channel_width_to_int(ci.chanwidth),
3218 ci.seg1_idx, &tx_chanwidth,
3219 &tx_seg1_idx) < 0)
3220 return;
3221
Hai Shalom899fcc72020-10-19 14:38:18 -07003222 res = ocv_verify_tx_params(kde.oci, kde.oci_len, &ci,
3223 tx_chanwidth, tx_seg1_idx);
3224 if (wpa_auth_uses_ocv(sm) == 2 && res == OCI_NOT_FOUND) {
3225 /* Work around misbehaving STAs */
3226 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
3227 "Disable OCV with a STA that does not send OCI");
3228 wpa_auth_set_ocv(sm, 0);
3229 } else if (res != OCI_SUCCESS) {
3230 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
3231 "OCV failed: %s", ocv_errorstr);
3232 if (wpa_auth->conf.msg_ctx)
3233 wpa_msg(wpa_auth->conf.msg_ctx, MSG_INFO,
3234 OCV_FAILURE "addr=" MACSTR
3235 " frame=eapol-key-m2 error=%s",
3236 MAC2STR(sm->addr), ocv_errorstr);
Hai Shalom74f70d42019-02-11 14:42:39 -08003237 return;
3238 }
3239 }
3240#endif /* CONFIG_OCV */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003241#ifdef CONFIG_IEEE80211R_AP
3242 if (ft && ft_check_msg_2_of_4(wpa_auth, sm, &kde) < 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003243 wpa_sta_disconnect(wpa_auth, sm->addr,
3244 WLAN_REASON_PREV_AUTH_NOT_VALID);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003245 return;
3246 }
3247#endif /* CONFIG_IEEE80211R_AP */
3248#ifdef CONFIG_P2P
3249 if (kde.ip_addr_req && kde.ip_addr_req[0] &&
3250 wpa_auth->ip_pool && WPA_GET_BE32(sm->ip_addr) == 0) {
3251 int idx;
3252 wpa_printf(MSG_DEBUG,
3253 "P2P: IP address requested in EAPOL-Key exchange");
3254 idx = bitfield_get_first_zero(wpa_auth->ip_pool);
3255 if (idx >= 0) {
3256 u32 start = WPA_GET_BE32(wpa_auth->conf.ip_addr_start);
3257 bitfield_set(wpa_auth->ip_pool, idx);
Sunil8cd6f4d2022-06-28 18:40:46 +00003258 sm->ip_addr_bit = idx;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003259 WPA_PUT_BE32(sm->ip_addr, start + idx);
3260 wpa_printf(MSG_DEBUG,
3261 "P2P: Assigned IP address %u.%u.%u.%u to "
Sunil8cd6f4d2022-06-28 18:40:46 +00003262 MACSTR " (bit %u)",
3263 sm->ip_addr[0], sm->ip_addr[1],
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003264 sm->ip_addr[2], sm->ip_addr[3],
Sunil8cd6f4d2022-06-28 18:40:46 +00003265 MAC2STR(sm->addr), sm->ip_addr_bit);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003266 }
3267 }
3268#endif /* CONFIG_P2P */
3269
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003270#ifdef CONFIG_DPP2
3271 if (DPP_VERSION > 1 && kde.dpp_kde) {
3272 wpa_printf(MSG_DEBUG,
3273 "DPP: peer Protocol Version %u Flags 0x%x",
3274 kde.dpp_kde[0], kde.dpp_kde[1]);
3275 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP &&
3276 wpa_auth->conf.dpp_pfs != 2 &&
3277 (kde.dpp_kde[1] & DPP_KDE_PFS_ALLOWED) &&
3278 !sm->dpp_z) {
3279 wpa_printf(MSG_INFO,
3280 "DPP: Peer indicated it supports PFS and local configuration allows this, but PFS was not negotiated for the association");
3281 wpa_sta_disconnect(wpa_auth, sm->addr,
3282 WLAN_REASON_PREV_AUTH_NOT_VALID);
3283 return;
3284 }
3285 }
3286#endif /* CONFIG_DPP2 */
3287
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003288#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003289 if (sm->wpa == WPA_VERSION_WPA2 && wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
3290 /*
3291 * Verify that PMKR1Name from EAPOL-Key message 2/4 matches
3292 * with the value we derived.
3293 */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003294 if (os_memcmp_const(sm->sup_pmk_r1_name, sm->pmk_r1_name,
3295 WPA_PMK_NAME_LEN) != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003296 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07003297 "PMKR1Name mismatch in FT 4-way handshake");
3298 wpa_hexdump(MSG_DEBUG,
3299 "FT: PMKR1Name from Supplicant",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003300 sm->sup_pmk_r1_name, WPA_PMK_NAME_LEN);
3301 wpa_hexdump(MSG_DEBUG, "FT: Derived PMKR1Name",
3302 sm->pmk_r1_name, WPA_PMK_NAME_LEN);
3303 return;
3304 }
3305 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003306#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003307
Hai Shalom021b0b52019-04-10 11:17:58 -07003308 if (vlan_id && wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
3309 wpa_auth_update_vlan(wpa_auth, sm->addr, vlan_id) < 0) {
3310 wpa_sta_disconnect(wpa_auth, sm->addr,
3311 WLAN_REASON_PREV_AUTH_NOT_VALID);
3312 return;
3313 }
3314
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003315 sm->pending_1_of_4_timeout = 0;
3316 eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm);
3317
Hai Shalom60840252021-02-19 19:02:11 -08003318 if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) && sm->PMK != pmk) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003319 /* PSK may have changed from the previous choice, so update
3320 * state machine data based on whatever PSK was selected here.
3321 */
3322 os_memcpy(sm->PMK, pmk, PMK_LEN);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003323 sm->pmk_len = PMK_LEN;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003324 }
3325
Hai Shalome21d4e82020-04-29 16:34:06 -07003326 sm->MICVerified = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003327
3328 os_memcpy(&sm->PTK, &PTK, sizeof(PTK));
Hai Shalom81f62d82019-07-22 12:10:00 -07003329 forced_memzero(&PTK, sizeof(PTK));
Hai Shalome21d4e82020-04-29 16:34:06 -07003330 sm->PTK_valid = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003331}
3332
3333
3334SM_STATE(WPA_PTK, PTKCALCNEGOTIATING2)
3335{
3336 SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING2, wpa_ptk);
3337 sm->TimeoutCtr = 0;
3338}
3339
3340
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003341static int ieee80211w_kde_len(struct wpa_state_machine *sm)
3342{
Hai Shalomfdcde762020-04-02 11:19:20 -07003343 size_t len = 0;
3344
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003345 if (sm->mgmt_frame_prot) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003346 len += 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN;
3347 len += wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
3348 }
3349 if (sm->mgmt_frame_prot && sm->wpa_auth->conf.beacon_prot) {
3350 len += 2 + RSN_SELECTOR_LEN + WPA_BIGTK_KDE_PREFIX_LEN;
3351 len += wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003352 }
3353
Hai Shalomfdcde762020-04-02 11:19:20 -07003354 return len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003355}
3356
3357
3358static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos)
3359{
3360 struct wpa_igtk_kde igtk;
Hai Shalomfdcde762020-04-02 11:19:20 -07003361 struct wpa_bigtk_kde bigtk;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003362 struct wpa_group *gsm = sm->group;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003363 u8 rsc[WPA_KEY_RSC_LEN];
Hai Shalomfdcde762020-04-02 11:19:20 -07003364 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
3365 size_t len = wpa_cipher_key_len(conf->group_mgmt_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003366
3367 if (!sm->mgmt_frame_prot)
3368 return pos;
3369
3370 igtk.keyid[0] = gsm->GN_igtk;
3371 igtk.keyid[1] = 0;
3372 if (gsm->wpa_group_state != WPA_GROUP_SETKEYSDONE ||
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003373 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, rsc) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003374 os_memset(igtk.pn, 0, sizeof(igtk.pn));
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003375 else
3376 os_memcpy(igtk.pn, rsc, sizeof(igtk.pn));
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003377 os_memcpy(igtk.igtk, gsm->IGTK[gsm->GN_igtk - 4], len);
Hai Shalomfdcde762020-04-02 11:19:20 -07003378 if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003379 /*
3380 * Provide unique random IGTK to each STA to prevent use of
3381 * IGTK in the BSS.
3382 */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003383 if (random_get_bytes(igtk.igtk, len) < 0)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003384 return pos;
3385 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003386 pos = wpa_add_kde(pos, RSN_KEY_DATA_IGTK,
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003387 (const u8 *) &igtk, WPA_IGTK_KDE_PREFIX_LEN + len,
3388 NULL, 0);
Sunil Ravia04bd252022-05-02 22:54:18 -07003389 forced_memzero(&igtk, sizeof(igtk));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003390
Hai Shalomfdcde762020-04-02 11:19:20 -07003391 if (!conf->beacon_prot)
3392 return pos;
3393
3394 bigtk.keyid[0] = gsm->GN_bigtk;
3395 bigtk.keyid[1] = 0;
3396 if (gsm->wpa_group_state != WPA_GROUP_SETKEYSDONE ||
3397 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_bigtk, rsc) < 0)
3398 os_memset(bigtk.pn, 0, sizeof(bigtk.pn));
3399 else
3400 os_memcpy(bigtk.pn, rsc, sizeof(bigtk.pn));
3401 os_memcpy(bigtk.bigtk, gsm->BIGTK[gsm->GN_bigtk - 6], len);
Hai Shalom899fcc72020-10-19 14:38:18 -07003402 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
3403 /*
3404 * Provide unique random BIGTK to each OSEN STA to prevent use
3405 * of BIGTK in the BSS.
3406 */
3407 if (random_get_bytes(bigtk.bigtk, len) < 0)
3408 return pos;
3409 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003410 pos = wpa_add_kde(pos, RSN_KEY_DATA_BIGTK,
3411 (const u8 *) &bigtk, WPA_BIGTK_KDE_PREFIX_LEN + len,
3412 NULL, 0);
Sunil Ravia04bd252022-05-02 22:54:18 -07003413 forced_memzero(&bigtk, sizeof(bigtk));
Hai Shalomfdcde762020-04-02 11:19:20 -07003414
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003415 return pos;
3416}
3417
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003418
Hai Shalom74f70d42019-02-11 14:42:39 -08003419static int ocv_oci_len(struct wpa_state_machine *sm)
3420{
3421#ifdef CONFIG_OCV
3422 if (wpa_auth_uses_ocv(sm))
3423 return OCV_OCI_KDE_LEN;
3424#endif /* CONFIG_OCV */
3425 return 0;
3426}
3427
Hai Shalom899fcc72020-10-19 14:38:18 -07003428
3429static int ocv_oci_add(struct wpa_state_machine *sm, u8 **argpos,
3430 unsigned int freq)
Hai Shalom74f70d42019-02-11 14:42:39 -08003431{
3432#ifdef CONFIG_OCV
3433 struct wpa_channel_info ci;
3434
3435 if (!wpa_auth_uses_ocv(sm))
3436 return 0;
3437
3438 if (wpa_channel_info(sm->wpa_auth, &ci) != 0) {
3439 wpa_printf(MSG_WARNING,
3440 "Failed to get channel info for OCI element");
3441 return -1;
3442 }
Hai Shalom899fcc72020-10-19 14:38:18 -07003443#ifdef CONFIG_TESTING_OPTIONS
3444 if (freq) {
3445 wpa_printf(MSG_INFO,
3446 "TEST: Override OCI KDE frequency %d -> %u MHz",
3447 ci.frequency, freq);
3448 ci.frequency = freq;
3449 }
3450#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom74f70d42019-02-11 14:42:39 -08003451
3452 return ocv_insert_oci_kde(&ci, argpos);
3453#else /* CONFIG_OCV */
3454 return 0;
3455#endif /* CONFIG_OCV */
3456}
3457
3458
Hai Shalomfdcde762020-04-02 11:19:20 -07003459#ifdef CONFIG_TESTING_OPTIONS
3460static u8 * replace_ie(const char *name, const u8 *old_buf, size_t *len, u8 eid,
3461 const u8 *ie, size_t ie_len)
3462{
3463 const u8 *elem;
3464 u8 *buf;
3465
3466 wpa_printf(MSG_DEBUG, "TESTING: %s EAPOL override", name);
3467 wpa_hexdump(MSG_DEBUG, "TESTING: wpa_ie before override",
3468 old_buf, *len);
3469 buf = os_malloc(*len + ie_len);
3470 if (!buf)
3471 return NULL;
3472 os_memcpy(buf, old_buf, *len);
3473 elem = get_ie(buf, *len, eid);
3474 if (elem) {
3475 u8 elem_len = 2 + elem[1];
3476
3477 os_memmove((void *) elem, elem + elem_len,
3478 *len - (elem - buf) - elem_len);
3479 *len -= elem_len;
3480 }
3481 os_memcpy(buf + *len, ie, ie_len);
3482 *len += ie_len;
3483 wpa_hexdump(MSG_DEBUG, "TESTING: wpa_ie after EAPOL override",
3484 buf, *len);
3485
3486 return buf;
3487}
3488#endif /* CONFIG_TESTING_OPTIONS */
3489
3490
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003491SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
3492{
Hai Shaloma20dcd72022-02-04 13:43:00 -08003493 u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde = NULL, *pos, stub_gtk[32];
Sunil Ravia04bd252022-05-02 22:54:18 -07003494 size_t gtk_len, kde_len = 0, wpa_ie_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003495 struct wpa_group *gsm = sm->group;
3496 u8 *wpa_ie;
Hai Shalomfdcde762020-04-02 11:19:20 -07003497 int secure, gtkidx, encr = 0;
3498 u8 *wpa_ie_buf = NULL, *wpa_ie_buf2 = NULL;
3499 u8 hdr[2];
3500 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003501
3502 SM_ENTRY_MA(WPA_PTK, PTKINITNEGOTIATING, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07003503 sm->TimeoutEvt = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003504
3505 sm->TimeoutCtr++;
Hai Shalomfdcde762020-04-02 11:19:20 -07003506 if (conf->wpa_disable_eapol_key_retries && sm->TimeoutCtr > 1) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003507 /* Do not allow retransmission of EAPOL-Key msg 3/4 */
3508 return;
3509 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003510 if (sm->TimeoutCtr > conf->wpa_pairwise_update_count) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003511 /* No point in sending the EAPOL-Key - we will disconnect
3512 * immediately following this. */
3513 return;
3514 }
3515
3516 /* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, [MDIE],
Hai Shalomfdcde762020-04-02 11:19:20 -07003517 GTK[GN], IGTK, [BIGTK], [FTIE], [TIE * 2])
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003518 */
3519 os_memset(rsc, 0, WPA_KEY_RSC_LEN);
3520 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc);
3521 /* If FT is used, wpa_auth->wpa_ie includes both RSNIE and MDIE */
3522 wpa_ie = sm->wpa_auth->wpa_ie;
3523 wpa_ie_len = sm->wpa_auth->wpa_ie_len;
Hai Shalomfdcde762020-04-02 11:19:20 -07003524 if (sm->wpa == WPA_VERSION_WPA && (conf->wpa & WPA_PROTO_RSN) &&
3525 wpa_ie_len > wpa_ie[1] + 2U && wpa_ie[0] == WLAN_EID_RSN) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003526 /* WPA-only STA, remove RSN IE and possible MDIE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003527 wpa_ie = wpa_ie + wpa_ie[1] + 2;
Hai Shalom60840252021-02-19 19:02:11 -08003528 if (wpa_ie[0] == WLAN_EID_RSNX)
3529 wpa_ie = wpa_ie + wpa_ie[1] + 2;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003530 if (wpa_ie[0] == WLAN_EID_MOBILITY_DOMAIN)
3531 wpa_ie = wpa_ie + wpa_ie[1] + 2;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003532 wpa_ie_len = wpa_ie[1] + 2;
3533 }
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003534#ifdef CONFIG_TESTING_OPTIONS
Hai Shalomfdcde762020-04-02 11:19:20 -07003535 if (conf->rsne_override_eapol_set) {
3536 wpa_ie_buf2 = replace_ie(
3537 "RSNE", wpa_ie, &wpa_ie_len, WLAN_EID_RSN,
3538 conf->rsne_override_eapol,
3539 conf->rsne_override_eapol_len);
3540 if (!wpa_ie_buf2)
3541 goto done;
3542 wpa_ie = wpa_ie_buf2;
3543 }
3544 if (conf->rsnxe_override_eapol_set) {
3545 wpa_ie_buf = replace_ie(
3546 "RSNXE", wpa_ie, &wpa_ie_len, WLAN_EID_RSNX,
3547 conf->rsnxe_override_eapol,
3548 conf->rsnxe_override_eapol_len);
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003549 if (!wpa_ie_buf)
Hai Shalomfdcde762020-04-02 11:19:20 -07003550 goto done;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003551 wpa_ie = wpa_ie_buf;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003552 }
3553#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003554 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
3555 "sending 3/4 msg of 4-Way Handshake");
3556 if (sm->wpa == WPA_VERSION_WPA2) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003557 if (sm->use_ext_key_id && sm->TimeoutCtr == 1 &&
3558 wpa_auth_set_key(sm->wpa_auth, 0,
3559 wpa_cipher_to_alg(sm->pairwise),
3560 sm->addr,
3561 sm->keyidx_active, sm->PTK.tk,
3562 wpa_cipher_key_len(sm->pairwise),
3563 KEY_FLAG_PAIRWISE_RX)) {
3564 wpa_sta_disconnect(sm->wpa_auth, sm->addr,
3565 WLAN_REASON_PREV_AUTH_NOT_VALID);
3566 return;
3567 }
3568
Sunil Ravi89eba102022-09-13 21:04:37 -07003569#ifdef CONFIG_PASN
3570 if (sm->wpa_auth->conf.secure_ltf &&
3571 ieee802_11_rsnx_capab(sm->rsnxe,
3572 WLAN_RSNX_CAPAB_SECURE_LTF) &&
3573 wpa_auth_set_ltf_keyseed(sm->wpa_auth, sm->addr,
3574 sm->PTK.ltf_keyseed,
3575 sm->PTK.ltf_keyseed_len)) {
3576 wpa_printf(MSG_ERROR,
3577 "WPA: Failed to set LTF keyseed to driver");
3578 wpa_sta_disconnect(sm->wpa_auth, sm->addr,
3579 WLAN_REASON_PREV_AUTH_NOT_VALID);
3580 return;
3581 }
3582#endif /* CONFIG_PASN */
3583
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003584 /* WPA2 send GTK in the 4-way handshake */
3585 secure = 1;
3586 gtk = gsm->GTK[gsm->GN - 1];
3587 gtk_len = gsm->GTK_len;
Hai Shalomfdcde762020-04-02 11:19:20 -07003588 if (conf->disable_gtk ||
Roshan Pius3a1667e2018-07-03 15:17:14 -07003589 sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003590 /*
3591 * Provide unique random GTK to each STA to prevent use
3592 * of GTK in the BSS.
3593 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003594 if (random_get_bytes(stub_gtk, gtk_len) < 0)
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003595 goto done;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003596 gtk = stub_gtk;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003597 }
Hai Shalomc3565922019-10-28 11:58:20 -07003598 gtkidx = gsm->GN;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003599 _rsc = rsc;
3600 encr = 1;
3601 } else {
3602 /* WPA does not include GTK in msg 3/4 */
3603 secure = 0;
3604 gtk = NULL;
3605 gtk_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003606 _rsc = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003607 if (sm->rx_eapol_key_secure) {
3608 /*
3609 * It looks like Windows 7 supplicant tries to use
3610 * Secure bit in msg 2/4 after having reported Michael
3611 * MIC failure and it then rejects the 4-way handshake
3612 * if msg 3/4 does not set Secure bit. Work around this
3613 * by setting the Secure bit here even in the case of
3614 * WPA if the supplicant used it first.
3615 */
3616 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07003617 "STA used Secure bit in WPA msg 2/4 - set Secure for 3/4 as workaround");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003618 secure = 1;
3619 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003620 }
3621
Hai Shalom74f70d42019-02-11 14:42:39 -08003622 kde_len = wpa_ie_len + ieee80211w_kde_len(sm) + ocv_oci_len(sm);
Hai Shalomfdcde762020-04-02 11:19:20 -07003623
3624 if (sm->use_ext_key_id)
3625 kde_len += 2 + RSN_SELECTOR_LEN + 2;
3626
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003627 if (gtk)
3628 kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003629#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003630 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
3631 kde_len += 2 + PMKID_LEN; /* PMKR1Name into RSN IE */
3632 kde_len += 300; /* FTIE + 2 * TIE */
3633 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003634#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08003635#ifdef CONFIG_P2P
3636 if (WPA_GET_BE32(sm->ip_addr) > 0)
3637 kde_len += 2 + RSN_SELECTOR_LEN + 3 * 4;
3638#endif /* CONFIG_P2P */
Hai Shalomfdcde762020-04-02 11:19:20 -07003639
3640 if (conf->transition_disable)
3641 kde_len += 2 + RSN_SELECTOR_LEN + 1;
3642
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003643#ifdef CONFIG_DPP2
3644 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP)
3645 kde_len += 2 + RSN_SELECTOR_LEN + 2;
3646#endif /* CONFIG_DPP2 */
3647
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003648 kde = os_malloc(kde_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07003649 if (!kde)
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003650 goto done;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003651
3652 pos = kde;
3653 os_memcpy(pos, wpa_ie, wpa_ie_len);
3654 pos += wpa_ie_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003655#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003656 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08003657 int res;
3658 size_t elen;
3659
3660 elen = pos - kde;
3661 res = wpa_insert_pmkid(kde, &elen, sm->pmk_r1_name);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003662 if (res < 0) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003663 wpa_printf(MSG_ERROR,
3664 "FT: Failed to insert PMKR1Name into RSN IE in EAPOL-Key data");
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003665 goto done;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003666 }
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08003667 pos -= wpa_ie_len;
3668 pos += elen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003669 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003670#endif /* CONFIG_IEEE80211R_AP */
Hai Shalomfdcde762020-04-02 11:19:20 -07003671 hdr[1] = 0;
3672
3673 if (sm->use_ext_key_id) {
3674 hdr[0] = sm->keyidx_active & 0x01;
3675 pos = wpa_add_kde(pos, RSN_KEY_DATA_KEYID, hdr, 2, NULL, 0);
3676 }
3677
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003678 if (gtk) {
Hai Shalomc3565922019-10-28 11:58:20 -07003679 hdr[0] = gtkidx & 0x03;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003680 pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
3681 gtk, gtk_len);
3682 }
3683 pos = ieee80211w_kde_add(sm, pos);
Hai Shalom899fcc72020-10-19 14:38:18 -07003684 if (ocv_oci_add(sm, &pos, conf->oci_freq_override_eapol_m3) < 0)
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003685 goto done;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003686
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003687#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003688 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
3689 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003690
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08003691 if (sm->assoc_resp_ftie &&
3692 kde + kde_len - pos >= 2 + sm->assoc_resp_ftie[1]) {
3693 os_memcpy(pos, sm->assoc_resp_ftie,
3694 2 + sm->assoc_resp_ftie[1]);
3695 res = 2 + sm->assoc_resp_ftie[1];
3696 } else {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003697 int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt);
3698
3699 res = wpa_write_ftie(conf, use_sha384,
3700 conf->r0_key_holder,
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08003701 conf->r0_key_holder_len,
3702 NULL, NULL, pos,
3703 kde + kde_len - pos,
Hai Shalomfdcde762020-04-02 11:19:20 -07003704 NULL, 0, 0);
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08003705 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003706 if (res < 0) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003707 wpa_printf(MSG_ERROR,
3708 "FT: Failed to insert FTIE into EAPOL-Key Key Data");
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003709 goto done;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003710 }
3711 pos += res;
3712
3713 /* TIE[ReassociationDeadline] (TU) */
3714 *pos++ = WLAN_EID_TIMEOUT_INTERVAL;
3715 *pos++ = 5;
3716 *pos++ = WLAN_TIMEOUT_REASSOC_DEADLINE;
3717 WPA_PUT_LE32(pos, conf->reassociation_deadline);
3718 pos += 4;
3719
3720 /* TIE[KeyLifetime] (seconds) */
3721 *pos++ = WLAN_EID_TIMEOUT_INTERVAL;
3722 *pos++ = 5;
3723 *pos++ = WLAN_TIMEOUT_KEY_LIFETIME;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003724 WPA_PUT_LE32(pos, conf->r0_key_lifetime);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003725 pos += 4;
3726 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003727#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08003728#ifdef CONFIG_P2P
3729 if (WPA_GET_BE32(sm->ip_addr) > 0) {
3730 u8 addr[3 * 4];
3731 os_memcpy(addr, sm->ip_addr, 4);
Hai Shalomfdcde762020-04-02 11:19:20 -07003732 os_memcpy(addr + 4, conf->ip_addr_mask, 4);
3733 os_memcpy(addr + 8, conf->ip_addr_go, 4);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08003734 pos = wpa_add_kde(pos, WFA_KEY_DATA_IP_ADDR_ALLOC,
3735 addr, sizeof(addr), NULL, 0);
3736 }
3737#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003738
Hai Shalomfdcde762020-04-02 11:19:20 -07003739 if (conf->transition_disable)
3740 pos = wpa_add_kde(pos, WFA_KEY_DATA_TRANSITION_DISABLE,
3741 &conf->transition_disable, 1, NULL, 0);
3742
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003743#ifdef CONFIG_DPP2
3744 if (DPP_VERSION > 1 && sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP) {
3745 u8 payload[2];
3746
3747 payload[0] = DPP_VERSION; /* Protocol Version */
3748 payload[1] = 0; /* Flags */
3749 if (conf->dpp_pfs == 0)
3750 payload[1] |= DPP_KDE_PFS_ALLOWED;
3751 else if (conf->dpp_pfs == 1)
3752 payload[1] |= DPP_KDE_PFS_ALLOWED |
3753 DPP_KDE_PFS_REQUIRED;
3754 pos = wpa_add_kde(pos, WFA_KEY_DATA_DPP,
3755 payload, sizeof(payload), NULL, 0);
3756 }
3757#endif /* CONFIG_DPP2 */
3758
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003759 wpa_send_eapol(sm->wpa_auth, sm,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003760 (secure ? WPA_KEY_INFO_SECURE : 0) |
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003761 (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
3762 WPA_KEY_INFO_MIC : 0) |
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003763 WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL |
3764 WPA_KEY_INFO_KEY_TYPE,
Hai Shalomc3565922019-10-28 11:58:20 -07003765 _rsc, sm->ANonce, kde, pos - kde, 0, encr);
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003766done:
Sunil Ravia04bd252022-05-02 22:54:18 -07003767 bin_clear_free(kde, kde_len);
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003768 os_free(wpa_ie_buf);
Hai Shalomfdcde762020-04-02 11:19:20 -07003769 os_free(wpa_ie_buf2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003770}
3771
3772
3773SM_STATE(WPA_PTK, PTKINITDONE)
3774{
3775 SM_ENTRY_MA(WPA_PTK, PTKINITDONE, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07003776 sm->EAPOLKeyReceived = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003777 if (sm->Pair) {
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07003778 enum wpa_alg alg = wpa_cipher_to_alg(sm->pairwise);
3779 int klen = wpa_cipher_key_len(sm->pairwise);
Hai Shalomfdcde762020-04-02 11:19:20 -07003780 int res;
3781
3782 if (sm->use_ext_key_id)
3783 res = wpa_auth_set_key(sm->wpa_auth, 0, 0, sm->addr,
3784 sm->keyidx_active, NULL, 0,
3785 KEY_FLAG_PAIRWISE_RX_TX_MODIFY);
3786 else
3787 res = wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr,
3788 0, sm->PTK.tk, klen,
3789 KEY_FLAG_PAIRWISE_RX_TX);
3790 if (res) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003791 wpa_sta_disconnect(sm->wpa_auth, sm->addr,
3792 WLAN_REASON_PREV_AUTH_NOT_VALID);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003793 return;
3794 }
Sunil Ravi89eba102022-09-13 21:04:37 -07003795
3796#ifdef CONFIG_PASN
3797 if (sm->wpa_auth->conf.secure_ltf &&
3798 ieee802_11_rsnx_capab(sm->rsnxe,
3799 WLAN_RSNX_CAPAB_SECURE_LTF) &&
3800 wpa_auth_set_ltf_keyseed(sm->wpa_auth, sm->addr,
3801 sm->PTK.ltf_keyseed,
3802 sm->PTK.ltf_keyseed_len)) {
3803 wpa_printf(MSG_ERROR,
3804 "WPA: Failed to set LTF keyseed to driver");
3805 wpa_sta_disconnect(sm->wpa_auth, sm->addr,
3806 WLAN_REASON_PREV_AUTH_NOT_VALID);
3807 return;
3808 }
3809#endif /* CONFIG_PASN */
3810
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003811 /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */
Hai Shalome21d4e82020-04-29 16:34:06 -07003812 sm->pairwise_set = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003813
Hai Shalom81f62d82019-07-22 12:10:00 -07003814 wpa_auth_set_ptk_rekey_timer(sm);
Hai Shalom60840252021-02-19 19:02:11 -08003815 wpa_auth_store_ptksa(sm->wpa_auth, sm->addr, sm->pairwise,
3816 dot11RSNAConfigPMKLifetime, &sm->PTK);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003817
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003818 if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
3819 sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP ||
3820 sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003821 wpa_auth_set_eapol(sm->wpa_auth, sm->addr,
3822 WPA_EAPOL_authorized, 1);
3823 }
3824 }
3825
3826 if (0 /* IBSS == TRUE */) {
3827 sm->keycount++;
3828 if (sm->keycount == 2) {
3829 wpa_auth_set_eapol(sm->wpa_auth, sm->addr,
3830 WPA_EAPOL_portValid, 1);
3831 }
3832 } else {
3833 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid,
3834 1);
3835 }
Hai Shalome21d4e82020-04-29 16:34:06 -07003836 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyAvailable,
3837 false);
3838 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyDone, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003839 if (sm->wpa == WPA_VERSION_WPA)
Hai Shalome21d4e82020-04-29 16:34:06 -07003840 sm->PInitAKeys = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003841 else
Hai Shalome21d4e82020-04-29 16:34:06 -07003842 sm->has_GTK = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003843 wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO,
3844 "pairwise key handshake completed (%s)",
3845 sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN");
Hai Shaloma20dcd72022-02-04 13:43:00 -08003846 wpa_msg(sm->wpa_auth->conf.msg_ctx, MSG_INFO, "EAPOL-4WAY-HS-COMPLETED "
3847 MACSTR, MAC2STR(sm->addr));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003848
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003849#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003850 wpa_ft_push_pmk_r1(sm->wpa_auth, sm->addr);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003851#endif /* CONFIG_IEEE80211R_AP */
Sunil Ravia04bd252022-05-02 22:54:18 -07003852
3853 sm->ptkstart_without_success = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003854}
3855
3856
3857SM_STEP(WPA_PTK)
3858{
3859 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
Hai Shalomfdcde762020-04-02 11:19:20 -07003860 struct wpa_auth_config *conf = &wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003861
3862 if (sm->Init)
3863 SM_ENTER(WPA_PTK, INITIALIZE);
3864 else if (sm->Disconnect
3865 /* || FIX: dot11RSNAConfigSALifetime timeout */) {
3866 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
3867 "WPA_PTK: sm->Disconnect");
3868 SM_ENTER(WPA_PTK, DISCONNECT);
3869 }
3870 else if (sm->DeauthenticationRequest)
3871 SM_ENTER(WPA_PTK, DISCONNECTED);
3872 else if (sm->AuthenticationRequest)
3873 SM_ENTER(WPA_PTK, AUTHENTICATION);
3874 else if (sm->ReAuthenticationRequest)
3875 SM_ENTER(WPA_PTK, AUTHENTICATION2);
Jouni Malinen1420a892017-10-01 12:32:57 +03003876 else if (sm->PTKRequest) {
3877 if (wpa_auth_sm_ptk_update(sm) < 0)
3878 SM_ENTER(WPA_PTK, DISCONNECTED);
3879 else
3880 SM_ENTER(WPA_PTK, PTKSTART);
3881 } else switch (sm->wpa_ptk_state) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003882 case WPA_PTK_INITIALIZE:
3883 break;
3884 case WPA_PTK_DISCONNECT:
3885 SM_ENTER(WPA_PTK, DISCONNECTED);
3886 break;
3887 case WPA_PTK_DISCONNECTED:
3888 SM_ENTER(WPA_PTK, INITIALIZE);
3889 break;
3890 case WPA_PTK_AUTHENTICATION:
3891 SM_ENTER(WPA_PTK, AUTHENTICATION2);
3892 break;
3893 case WPA_PTK_AUTHENTICATION2:
3894 if (wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) &&
Hai Shalomfdcde762020-04-02 11:19:20 -07003895 wpa_auth_get_eapol(wpa_auth, sm->addr,
Hai Shalome21d4e82020-04-29 16:34:06 -07003896 WPA_EAPOL_keyRun))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003897 SM_ENTER(WPA_PTK, INITPMK);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003898 else if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
3899 sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003900 /* FIX: && 802.1X::keyRun */)
3901 SM_ENTER(WPA_PTK, INITPSK);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003902 else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP)
3903 SM_ENTER(WPA_PTK, INITPMK);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003904 break;
3905 case WPA_PTK_INITPMK:
Hai Shalomfdcde762020-04-02 11:19:20 -07003906 if (wpa_auth_get_eapol(wpa_auth, sm->addr,
Hai Shalome21d4e82020-04-29 16:34:06 -07003907 WPA_EAPOL_keyAvailable)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003908 SM_ENTER(WPA_PTK, PTKSTART);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003909#ifdef CONFIG_DPP
3910 } else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP && sm->pmksa) {
3911 SM_ENTER(WPA_PTK, PTKSTART);
3912#endif /* CONFIG_DPP */
3913 } else {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003914 wpa_auth->dot11RSNA4WayHandshakeFailures++;
Hai Shalomfdcde762020-04-02 11:19:20 -07003915 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003916 "INITPMK - keyAvailable = false");
3917 SM_ENTER(WPA_PTK, DISCONNECT);
3918 }
3919 break;
3920 case WPA_PTK_INITPSK:
Hai Shalomfdcde762020-04-02 11:19:20 -07003921 if (wpa_auth_get_psk(wpa_auth, sm->addr, sm->p2p_dev_addr,
Hai Shalom021b0b52019-04-10 11:17:58 -07003922 NULL, NULL, NULL)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003923 SM_ENTER(WPA_PTK, PTKSTART);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003924#ifdef CONFIG_SAE
3925 } else if (wpa_auth_uses_sae(sm) && sm->pmksa) {
3926 SM_ENTER(WPA_PTK, PTKSTART);
3927#endif /* CONFIG_SAE */
Sunil Ravia04bd252022-05-02 22:54:18 -07003928 } else if (wpa_key_mgmt_wpa_psk_no_sae(sm->wpa_key_mgmt) &&
3929 wpa_auth->conf.radius_psk) {
3930 wpa_printf(MSG_DEBUG,
3931 "INITPSK: No PSK yet available for STA - use RADIUS later");
3932 SM_ENTER(WPA_PTK, PTKSTART);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003933 } else {
Hai Shalomfdcde762020-04-02 11:19:20 -07003934 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003935 "no PSK configured for the STA");
3936 wpa_auth->dot11RSNA4WayHandshakeFailures++;
3937 SM_ENTER(WPA_PTK, DISCONNECT);
3938 }
3939 break;
3940 case WPA_PTK_PTKSTART:
3941 if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest &&
3942 sm->EAPOLKeyPairwise)
3943 SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING);
Hai Shalomfdcde762020-04-02 11:19:20 -07003944 else if (sm->TimeoutCtr > conf->wpa_pairwise_update_count) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003945 wpa_auth->dot11RSNA4WayHandshakeFailures++;
Hai Shalomfdcde762020-04-02 11:19:20 -07003946 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
3947 "PTKSTART: Retry limit %u reached",
3948 conf->wpa_pairwise_update_count);
Hai Shalome21d4e82020-04-29 16:34:06 -07003949 sm->disconnect_reason =
3950 WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003951 SM_ENTER(WPA_PTK, DISCONNECT);
3952 } else if (sm->TimeoutEvt)
3953 SM_ENTER(WPA_PTK, PTKSTART);
3954 break;
3955 case WPA_PTK_PTKCALCNEGOTIATING:
3956 if (sm->MICVerified)
3957 SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING2);
3958 else if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest &&
3959 sm->EAPOLKeyPairwise)
3960 SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING);
3961 else if (sm->TimeoutEvt)
3962 SM_ENTER(WPA_PTK, PTKSTART);
3963 break;
3964 case WPA_PTK_PTKCALCNEGOTIATING2:
3965 SM_ENTER(WPA_PTK, PTKINITNEGOTIATING);
3966 break;
3967 case WPA_PTK_PTKINITNEGOTIATING:
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003968 if (sm->update_snonce)
3969 SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING);
3970 else if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest &&
3971 sm->EAPOLKeyPairwise && sm->MICVerified)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003972 SM_ENTER(WPA_PTK, PTKINITDONE);
3973 else if (sm->TimeoutCtr >
Hai Shalomfdcde762020-04-02 11:19:20 -07003974 conf->wpa_pairwise_update_count ||
3975 (conf->wpa_disable_eapol_key_retries &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003976 sm->TimeoutCtr > 1)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003977 wpa_auth->dot11RSNA4WayHandshakeFailures++;
Hai Shalomfdcde762020-04-02 11:19:20 -07003978 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
3979 "PTKINITNEGOTIATING: Retry limit %u reached",
3980 conf->wpa_pairwise_update_count);
Hai Shalome21d4e82020-04-29 16:34:06 -07003981 sm->disconnect_reason =
3982 WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003983 SM_ENTER(WPA_PTK, DISCONNECT);
3984 } else if (sm->TimeoutEvt)
3985 SM_ENTER(WPA_PTK, PTKINITNEGOTIATING);
3986 break;
3987 case WPA_PTK_PTKINITDONE:
3988 break;
3989 }
3990}
3991
3992
3993SM_STATE(WPA_PTK_GROUP, IDLE)
3994{
3995 SM_ENTRY_MA(WPA_PTK_GROUP, IDLE, wpa_ptk_group);
3996 if (sm->Init) {
3997 /* Init flag is not cleared here, so avoid busy
3998 * loop by claiming nothing changed. */
Hai Shalome21d4e82020-04-29 16:34:06 -07003999 sm->changed = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004000 }
4001 sm->GTimeoutCtr = 0;
4002}
4003
4004
4005SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING)
4006{
4007 u8 rsc[WPA_KEY_RSC_LEN];
4008 struct wpa_group *gsm = sm->group;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004009 const u8 *kde;
4010 u8 *kde_buf = NULL, *pos, hdr[2];
Sunil Ravia04bd252022-05-02 22:54:18 -07004011 size_t kde_len = 0;
Hai Shaloma20dcd72022-02-04 13:43:00 -08004012 u8 *gtk, stub_gtk[32];
Hai Shalomfdcde762020-04-02 11:19:20 -07004013 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004014
4015 SM_ENTRY_MA(WPA_PTK_GROUP, REKEYNEGOTIATING, wpa_ptk_group);
4016
4017 sm->GTimeoutCtr++;
Hai Shalomfdcde762020-04-02 11:19:20 -07004018 if (conf->wpa_disable_eapol_key_retries && sm->GTimeoutCtr > 1) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004019 /* Do not allow retransmission of EAPOL-Key group msg 1/2 */
4020 return;
4021 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004022 if (sm->GTimeoutCtr > conf->wpa_group_update_count) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004023 /* No point in sending the EAPOL-Key - we will disconnect
4024 * immediately following this. */
4025 return;
4026 }
4027
4028 if (sm->wpa == WPA_VERSION_WPA)
Hai Shalome21d4e82020-04-29 16:34:06 -07004029 sm->PInitAKeys = false;
4030 sm->TimeoutEvt = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004031 /* Send EAPOL(1, 1, 1, !Pair, G, RSC, GNonce, MIC(PTK), GTK[GN]) */
4032 os_memset(rsc, 0, WPA_KEY_RSC_LEN);
4033 if (gsm->wpa_group_state == WPA_GROUP_SETKEYSDONE)
4034 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc);
4035 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
4036 "sending 1/2 msg of Group Key Handshake");
4037
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004038 gtk = gsm->GTK[gsm->GN - 1];
Hai Shalomfdcde762020-04-02 11:19:20 -07004039 if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004040 /*
4041 * Provide unique random GTK to each STA to prevent use
4042 * of GTK in the BSS.
4043 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08004044 if (random_get_bytes(stub_gtk, gsm->GTK_len) < 0)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004045 return;
Hai Shaloma20dcd72022-02-04 13:43:00 -08004046 gtk = stub_gtk;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004047 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004048 if (sm->wpa == WPA_VERSION_WPA2) {
4049 kde_len = 2 + RSN_SELECTOR_LEN + 2 + gsm->GTK_len +
Hai Shalom74f70d42019-02-11 14:42:39 -08004050 ieee80211w_kde_len(sm) + ocv_oci_len(sm);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004051 kde_buf = os_malloc(kde_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07004052 if (!kde_buf)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004053 return;
4054
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004055 kde = pos = kde_buf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004056 hdr[0] = gsm->GN & 0x03;
4057 hdr[1] = 0;
4058 pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004059 gtk, gsm->GTK_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004060 pos = ieee80211w_kde_add(sm, pos);
Hai Shalom899fcc72020-10-19 14:38:18 -07004061 if (ocv_oci_add(sm, &pos,
4062 conf->oci_freq_override_eapol_g1) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -08004063 os_free(kde_buf);
4064 return;
4065 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004066 kde_len = pos - kde;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004067 } else {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004068 kde = gtk;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004069 kde_len = gsm->GTK_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004070 }
4071
4072 wpa_send_eapol(sm->wpa_auth, sm,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004073 WPA_KEY_INFO_SECURE |
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004074 (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
4075 WPA_KEY_INFO_MIC : 0) |
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004076 WPA_KEY_INFO_ACK |
4077 (!sm->Pair ? WPA_KEY_INFO_INSTALL : 0),
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004078 rsc, NULL, kde, kde_len, gsm->GN, 1);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004079
Sunil Ravia04bd252022-05-02 22:54:18 -07004080 bin_clear_free(kde_buf, kde_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004081}
4082
4083
4084SM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED)
4085{
Hai Shalom74f70d42019-02-11 14:42:39 -08004086 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
Hai Shalomfdcde762020-04-02 11:19:20 -07004087#ifdef CONFIG_OCV
Hai Shalom74f70d42019-02-11 14:42:39 -08004088 const u8 *key_data, *mic;
4089 struct ieee802_1x_hdr *hdr;
4090 struct wpa_eapol_key *key;
4091 struct wpa_eapol_ie_parse kde;
4092 size_t mic_len;
4093 u16 key_data_length;
4094#endif /* CONFIG_OCV */
4095
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004096 SM_ENTRY_MA(WPA_PTK_GROUP, REKEYESTABLISHED, wpa_ptk_group);
Hai Shalome21d4e82020-04-29 16:34:06 -07004097 sm->EAPOLKeyReceived = false;
Hai Shalom74f70d42019-02-11 14:42:39 -08004098
4099#ifdef CONFIG_OCV
4100 mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
4101
4102 /*
4103 * Note: last_rx_eapol_key length fields have already been validated in
4104 * wpa_receive().
4105 */
4106 hdr = (struct ieee802_1x_hdr *) sm->last_rx_eapol_key;
4107 key = (struct wpa_eapol_key *) (hdr + 1);
4108 mic = (u8 *) (key + 1);
4109 key_data = mic + mic_len + 2;
4110 key_data_length = WPA_GET_BE16(mic + mic_len);
4111 if (key_data_length > sm->last_rx_eapol_key_len - sizeof(*hdr) -
4112 sizeof(*key) - mic_len - 2)
4113 return;
4114
4115 if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) {
4116 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
4117 "received EAPOL-Key group msg 2/2 with invalid Key Data contents");
4118 return;
4119 }
4120
4121 if (wpa_auth_uses_ocv(sm)) {
4122 struct wpa_channel_info ci;
4123 int tx_chanwidth;
4124 int tx_seg1_idx;
4125
4126 if (wpa_channel_info(wpa_auth, &ci) != 0) {
4127 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalom899fcc72020-10-19 14:38:18 -07004128 "Failed to get channel info to validate received OCI in EAPOL-Key group 2/2");
Hai Shalom74f70d42019-02-11 14:42:39 -08004129 return;
4130 }
4131
4132 if (get_sta_tx_parameters(sm,
4133 channel_width_to_int(ci.chanwidth),
4134 ci.seg1_idx, &tx_chanwidth,
4135 &tx_seg1_idx) < 0)
4136 return;
4137
4138 if (ocv_verify_tx_params(kde.oci, kde.oci_len, &ci,
Hai Shalom899fcc72020-10-19 14:38:18 -07004139 tx_chanwidth, tx_seg1_idx) !=
4140 OCI_SUCCESS) {
4141 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
4142 "OCV failed: %s", ocv_errorstr);
4143 if (wpa_auth->conf.msg_ctx)
4144 wpa_msg(wpa_auth->conf.msg_ctx, MSG_INFO,
4145 OCV_FAILURE "addr=" MACSTR
4146 " frame=eapol-key-g2 error=%s",
4147 MAC2STR(sm->addr), ocv_errorstr);
Hai Shalom74f70d42019-02-11 14:42:39 -08004148 return;
4149 }
4150 }
4151#endif /* CONFIG_OCV */
4152
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004153 if (sm->GUpdateStationKeys)
4154 sm->group->GKeyDoneStations--;
Hai Shalome21d4e82020-04-29 16:34:06 -07004155 sm->GUpdateStationKeys = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004156 sm->GTimeoutCtr = 0;
4157 /* FIX: MLME.SetProtection.Request(TA, Tx_Rx) */
Hai Shalomfdcde762020-04-02 11:19:20 -07004158 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004159 "group key handshake completed (%s)",
4160 sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN");
Hai Shalome21d4e82020-04-29 16:34:06 -07004161 sm->has_GTK = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004162}
4163
4164
4165SM_STATE(WPA_PTK_GROUP, KEYERROR)
4166{
4167 SM_ENTRY_MA(WPA_PTK_GROUP, KEYERROR, wpa_ptk_group);
4168 if (sm->GUpdateStationKeys)
4169 sm->group->GKeyDoneStations--;
Hai Shalome21d4e82020-04-29 16:34:06 -07004170 sm->GUpdateStationKeys = false;
4171 sm->Disconnect = true;
4172 sm->disconnect_reason = WLAN_REASON_GROUP_KEY_UPDATE_TIMEOUT;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004173 wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO,
4174 "group key handshake failed (%s) after %u tries",
4175 sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN",
4176 sm->wpa_auth->conf.wpa_group_update_count);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004177}
4178
4179
4180SM_STEP(WPA_PTK_GROUP)
4181{
4182 if (sm->Init || sm->PtkGroupInit) {
4183 SM_ENTER(WPA_PTK_GROUP, IDLE);
Hai Shalome21d4e82020-04-29 16:34:06 -07004184 sm->PtkGroupInit = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004185 } else switch (sm->wpa_ptk_group_state) {
4186 case WPA_PTK_GROUP_IDLE:
4187 if (sm->GUpdateStationKeys ||
4188 (sm->wpa == WPA_VERSION_WPA && sm->PInitAKeys))
4189 SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING);
4190 break;
4191 case WPA_PTK_GROUP_REKEYNEGOTIATING:
4192 if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest &&
4193 !sm->EAPOLKeyPairwise && sm->MICVerified)
4194 SM_ENTER(WPA_PTK_GROUP, REKEYESTABLISHED);
4195 else if (sm->GTimeoutCtr >
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004196 sm->wpa_auth->conf.wpa_group_update_count ||
4197 (sm->wpa_auth->conf.wpa_disable_eapol_key_retries &&
4198 sm->GTimeoutCtr > 1))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004199 SM_ENTER(WPA_PTK_GROUP, KEYERROR);
4200 else if (sm->TimeoutEvt)
4201 SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING);
4202 break;
4203 case WPA_PTK_GROUP_KEYERROR:
4204 SM_ENTER(WPA_PTK_GROUP, IDLE);
4205 break;
4206 case WPA_PTK_GROUP_REKEYESTABLISHED:
4207 SM_ENTER(WPA_PTK_GROUP, IDLE);
4208 break;
4209 }
4210}
4211
4212
4213static int wpa_gtk_update(struct wpa_authenticator *wpa_auth,
4214 struct wpa_group *group)
4215{
Hai Shalomfdcde762020-04-02 11:19:20 -07004216 struct wpa_auth_config *conf = &wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004217 int ret = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07004218 size_t len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004219
4220 os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
4221 inc_byte_array(group->Counter, WPA_NONCE_LEN);
4222 if (wpa_gmk_to_gtk(group->GMK, "Group key expansion",
4223 wpa_auth->addr, group->GNonce,
4224 group->GTK[group->GN - 1], group->GTK_len) < 0)
4225 ret = -1;
4226 wpa_hexdump_key(MSG_DEBUG, "GTK",
4227 group->GTK[group->GN - 1], group->GTK_len);
4228
Hai Shalomfdcde762020-04-02 11:19:20 -07004229 if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
4230 len = wpa_cipher_key_len(conf->group_mgmt_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004231 os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
4232 inc_byte_array(group->Counter, WPA_NONCE_LEN);
4233 if (wpa_gmk_to_gtk(group->GMK, "IGTK key expansion",
4234 wpa_auth->addr, group->GNonce,
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004235 group->IGTK[group->GN_igtk - 4], len) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004236 ret = -1;
4237 wpa_hexdump_key(MSG_DEBUG, "IGTK",
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004238 group->IGTK[group->GN_igtk - 4], len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004239 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004240
Hai Shalomfdcde762020-04-02 11:19:20 -07004241 if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION &&
4242 conf->beacon_prot) {
4243 len = wpa_cipher_key_len(conf->group_mgmt_cipher);
4244 os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
4245 inc_byte_array(group->Counter, WPA_NONCE_LEN);
4246 if (wpa_gmk_to_gtk(group->GMK, "BIGTK key expansion",
4247 wpa_auth->addr, group->GNonce,
4248 group->BIGTK[group->GN_bigtk - 6], len) < 0)
4249 ret = -1;
4250 wpa_hexdump_key(MSG_DEBUG, "BIGTK",
4251 group->BIGTK[group->GN_bigtk - 6], len);
4252 }
4253
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004254 return ret;
4255}
4256
4257
4258static void wpa_group_gtk_init(struct wpa_authenticator *wpa_auth,
4259 struct wpa_group *group)
4260{
Hai Shalomfdcde762020-04-02 11:19:20 -07004261 wpa_printf(MSG_DEBUG,
4262 "WPA: group state machine entering state GTK_INIT (VLAN-ID %d)",
4263 group->vlan_id);
Hai Shalome21d4e82020-04-29 16:34:06 -07004264 group->changed = false; /* GInit is not cleared here; avoid loop */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004265 group->wpa_group_state = WPA_GROUP_GTK_INIT;
4266
4267 /* GTK[0..N] = 0 */
4268 os_memset(group->GTK, 0, sizeof(group->GTK));
4269 group->GN = 1;
4270 group->GM = 2;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004271 group->GN_igtk = 4;
4272 group->GM_igtk = 5;
Hai Shalomfdcde762020-04-02 11:19:20 -07004273 group->GN_bigtk = 6;
4274 group->GM_bigtk = 7;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004275 /* GTK[GN] = CalcGTK() */
4276 wpa_gtk_update(wpa_auth, group);
4277}
4278
4279
4280static int wpa_group_update_sta(struct wpa_state_machine *sm, void *ctx)
4281{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004282 if (ctx != NULL && ctx != sm->group)
4283 return 0;
4284
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004285 if (sm->wpa_ptk_state != WPA_PTK_PTKINITDONE) {
4286 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
4287 "Not in PTKINITDONE; skip Group Key update");
Hai Shalome21d4e82020-04-29 16:34:06 -07004288 sm->GUpdateStationKeys = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004289 return 0;
4290 }
4291 if (sm->GUpdateStationKeys) {
4292 /*
4293 * This should not really happen, so add a debug log entry.
4294 * Since we clear the GKeyDoneStations before the loop, the
4295 * station needs to be counted here anyway.
4296 */
4297 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07004298 "GUpdateStationKeys was already set when marking station for GTK rekeying");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004299 }
4300
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004301 /* Do not rekey GTK/IGTK when STA is in WNM-Sleep Mode */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004302 if (sm->is_wnmsleep)
4303 return 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004304
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004305 sm->group->GKeyDoneStations++;
Hai Shalome21d4e82020-04-29 16:34:06 -07004306 sm->GUpdateStationKeys = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004307
4308 wpa_sm_step(sm);
4309 return 0;
4310}
4311
4312
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004313#ifdef CONFIG_WNM_AP
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004314/* update GTK when exiting WNM-Sleep Mode */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004315void wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm)
4316{
Hai Shalomfdcde762020-04-02 11:19:20 -07004317 if (!sm || sm->is_wnmsleep)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004318 return;
4319
4320 wpa_group_update_sta(sm, NULL);
4321}
4322
4323
4324void wpa_set_wnmsleep(struct wpa_state_machine *sm, int flag)
4325{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004326 if (sm)
4327 sm->is_wnmsleep = !!flag;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004328}
4329
4330
4331int wpa_wnmsleep_gtk_subelem(struct wpa_state_machine *sm, u8 *pos)
4332{
Hai Shalom899fcc72020-10-19 14:38:18 -07004333 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004334 struct wpa_group *gsm = sm->group;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004335 u8 *start = pos;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004336
4337 /*
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004338 * GTK subelement:
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004339 * Sub-elem ID[1] | Length[1] | Key Info[2] | Key Length[1] | RSC[8] |
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004340 * Key[5..32]
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004341 */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004342 *pos++ = WNM_SLEEP_SUBELEM_GTK;
4343 *pos++ = 11 + gsm->GTK_len;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004344 /* Key ID in B0-B1 of Key Info */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004345 WPA_PUT_LE16(pos, gsm->GN & 0x03);
4346 pos += 2;
4347 *pos++ = gsm->GTK_len;
4348 if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, pos) != 0)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004349 return 0;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004350 pos += 8;
4351 os_memcpy(pos, gsm->GTK[gsm->GN - 1], gsm->GTK_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07004352 if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
4353 /*
4354 * Provide unique random GTK to each STA to prevent use
4355 * of GTK in the BSS.
4356 */
4357 if (random_get_bytes(pos, gsm->GTK_len) < 0)
4358 return 0;
4359 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004360 pos += gsm->GTK_len;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004361
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004362 wpa_printf(MSG_DEBUG, "WNM: GTK Key ID %u in WNM-Sleep Mode exit",
4363 gsm->GN);
4364 wpa_hexdump_key(MSG_DEBUG, "WNM: GTK in WNM-Sleep Mode exit",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004365 gsm->GTK[gsm->GN - 1], gsm->GTK_len);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004366
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004367 return pos - start;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004368}
4369
4370
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004371int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos)
4372{
Hai Shalom899fcc72020-10-19 14:38:18 -07004373 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004374 struct wpa_group *gsm = sm->group;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004375 u8 *start = pos;
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004376 size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004377
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004378 /*
4379 * IGTK subelement:
4380 * Sub-elem ID[1] | Length[1] | KeyID[2] | PN[6] | Key[16]
4381 */
4382 *pos++ = WNM_SLEEP_SUBELEM_IGTK;
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004383 *pos++ = 2 + 6 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004384 WPA_PUT_LE16(pos, gsm->GN_igtk);
4385 pos += 2;
4386 if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, pos) != 0)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004387 return 0;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004388 pos += 6;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004389
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004390 os_memcpy(pos, gsm->IGTK[gsm->GN_igtk - 4], len);
Hai Shalom899fcc72020-10-19 14:38:18 -07004391 if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
4392 /*
4393 * Provide unique random IGTK to each STA to prevent use
4394 * of IGTK in the BSS.
4395 */
4396 if (random_get_bytes(pos, len) < 0)
4397 return 0;
4398 }
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004399 pos += len;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004400
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004401 wpa_printf(MSG_DEBUG, "WNM: IGTK Key ID %u in WNM-Sleep Mode exit",
4402 gsm->GN_igtk);
4403 wpa_hexdump_key(MSG_DEBUG, "WNM: IGTK in WNM-Sleep Mode exit",
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004404 gsm->IGTK[gsm->GN_igtk - 4], len);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004405
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004406 return pos - start;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004407}
Hai Shalomc3565922019-10-28 11:58:20 -07004408
Hai Shalomfdcde762020-04-02 11:19:20 -07004409
4410int wpa_wnmsleep_bigtk_subelem(struct wpa_state_machine *sm, u8 *pos)
4411{
4412 struct wpa_group *gsm = sm->group;
4413 u8 *start = pos;
4414 size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
4415
4416 /*
4417 * BIGTK subelement:
4418 * Sub-elem ID[1] | Length[1] | KeyID[2] | PN[6] | Key[16]
4419 */
4420 *pos++ = WNM_SLEEP_SUBELEM_BIGTK;
4421 *pos++ = 2 + 6 + len;
4422 WPA_PUT_LE16(pos, gsm->GN_bigtk);
4423 pos += 2;
4424 if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_bigtk, pos) != 0)
4425 return 0;
4426 pos += 6;
4427
4428 os_memcpy(pos, gsm->BIGTK[gsm->GN_bigtk - 6], len);
Hai Shalom899fcc72020-10-19 14:38:18 -07004429 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
4430 /*
4431 * Provide unique random BIGTK to each STA to prevent use
4432 * of BIGTK in the BSS.
4433 */
4434 if (random_get_bytes(pos, len) < 0)
4435 return 0;
4436 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004437 pos += len;
4438
4439 wpa_printf(MSG_DEBUG, "WNM: BIGTK Key ID %u in WNM-Sleep Mode exit",
4440 gsm->GN_bigtk);
4441 wpa_hexdump_key(MSG_DEBUG, "WNM: BIGTK in WNM-Sleep Mode exit",
Hai Shaloma20dcd72022-02-04 13:43:00 -08004442 gsm->BIGTK[gsm->GN_bigtk - 6], len);
Hai Shalomfdcde762020-04-02 11:19:20 -07004443
4444 return pos - start;
4445}
4446
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004447#endif /* CONFIG_WNM_AP */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004448
4449
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004450static void wpa_group_setkeys(struct wpa_authenticator *wpa_auth,
4451 struct wpa_group *group)
4452{
4453 int tmp;
4454
Hai Shalomfdcde762020-04-02 11:19:20 -07004455 wpa_printf(MSG_DEBUG,
4456 "WPA: group state machine entering state SETKEYS (VLAN-ID %d)",
4457 group->vlan_id);
Hai Shalome21d4e82020-04-29 16:34:06 -07004458 group->changed = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004459 group->wpa_group_state = WPA_GROUP_SETKEYS;
Hai Shalome21d4e82020-04-29 16:34:06 -07004460 group->GTKReKey = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004461 tmp = group->GM;
4462 group->GM = group->GN;
4463 group->GN = tmp;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004464 tmp = group->GM_igtk;
4465 group->GM_igtk = group->GN_igtk;
4466 group->GN_igtk = tmp;
Hai Shalomfdcde762020-04-02 11:19:20 -07004467 tmp = group->GM_bigtk;
4468 group->GM_bigtk = group->GN_bigtk;
4469 group->GN_bigtk = tmp;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004470 /* "GKeyDoneStations = GNoStations" is done in more robust way by
4471 * counting the STAs that are marked with GUpdateStationKeys instead of
4472 * including all STAs that could be in not-yet-completed state. */
4473 wpa_gtk_update(wpa_auth, group);
4474
4475 if (group->GKeyDoneStations) {
Hai Shalomfdcde762020-04-02 11:19:20 -07004476 wpa_printf(MSG_DEBUG,
4477 "wpa_group_setkeys: Unexpected GKeyDoneStations=%d when starting new GTK rekey",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004478 group->GKeyDoneStations);
4479 group->GKeyDoneStations = 0;
4480 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004481 wpa_auth_for_each_sta(wpa_auth, wpa_group_update_sta, group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004482 wpa_printf(MSG_DEBUG, "wpa_group_setkeys: GKeyDoneStations=%d",
4483 group->GKeyDoneStations);
4484}
4485
4486
4487static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth,
4488 struct wpa_group *group)
4489{
Hai Shalomfdcde762020-04-02 11:19:20 -07004490 struct wpa_auth_config *conf = &wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004491 int ret = 0;
4492
4493 if (wpa_auth_set_key(wpa_auth, group->vlan_id,
Hai Shalomfdcde762020-04-02 11:19:20 -07004494 wpa_cipher_to_alg(conf->wpa_group),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004495 broadcast_ether_addr, group->GN,
Hai Shalomfdcde762020-04-02 11:19:20 -07004496 group->GTK[group->GN - 1], group->GTK_len,
4497 KEY_FLAG_GROUP_TX_DEFAULT) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004498 ret = -1;
4499
Hai Shalomfdcde762020-04-02 11:19:20 -07004500 if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004501 enum wpa_alg alg;
4502 size_t len;
4503
Hai Shalomfdcde762020-04-02 11:19:20 -07004504 alg = wpa_cipher_to_alg(conf->group_mgmt_cipher);
4505 len = wpa_cipher_key_len(conf->group_mgmt_cipher);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004506
4507 if (ret == 0 &&
4508 wpa_auth_set_key(wpa_auth, group->vlan_id, alg,
4509 broadcast_ether_addr, group->GN_igtk,
Hai Shalomfdcde762020-04-02 11:19:20 -07004510 group->IGTK[group->GN_igtk - 4], len,
4511 KEY_FLAG_GROUP_TX_DEFAULT) < 0)
4512 ret = -1;
4513
4514 if (ret == 0 && conf->beacon_prot &&
4515 wpa_auth_set_key(wpa_auth, group->vlan_id, alg,
4516 broadcast_ether_addr, group->GN_bigtk,
4517 group->BIGTK[group->GN_bigtk - 6], len,
4518 KEY_FLAG_GROUP_TX_DEFAULT) < 0)
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004519 ret = -1;
4520 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004521
4522 return ret;
4523}
4524
4525
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004526static int wpa_group_disconnect_cb(struct wpa_state_machine *sm, void *ctx)
4527{
4528 if (sm->group == ctx) {
4529 wpa_printf(MSG_DEBUG, "WPA: Mark STA " MACSTR
Hai Shalomfdcde762020-04-02 11:19:20 -07004530 " for disconnection due to fatal failure",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004531 MAC2STR(sm->addr));
Hai Shalome21d4e82020-04-29 16:34:06 -07004532 sm->Disconnect = true;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004533 }
4534
4535 return 0;
4536}
4537
4538
4539static void wpa_group_fatal_failure(struct wpa_authenticator *wpa_auth,
4540 struct wpa_group *group)
4541{
Hai Shalomfdcde762020-04-02 11:19:20 -07004542 wpa_printf(MSG_DEBUG,
4543 "WPA: group state machine entering state FATAL_FAILURE");
Hai Shalome21d4e82020-04-29 16:34:06 -07004544 group->changed = true;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004545 group->wpa_group_state = WPA_GROUP_FATAL_FAILURE;
4546 wpa_auth_for_each_sta(wpa_auth, wpa_group_disconnect_cb, group);
4547}
4548
4549
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004550static int wpa_group_setkeysdone(struct wpa_authenticator *wpa_auth,
4551 struct wpa_group *group)
4552{
Hai Shalomfdcde762020-04-02 11:19:20 -07004553 wpa_printf(MSG_DEBUG,
4554 "WPA: group state machine entering state SETKEYSDONE (VLAN-ID %d)",
4555 group->vlan_id);
Hai Shalome21d4e82020-04-29 16:34:06 -07004556 group->changed = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004557 group->wpa_group_state = WPA_GROUP_SETKEYSDONE;
4558
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004559 if (wpa_group_config_group_keys(wpa_auth, group) < 0) {
4560 wpa_group_fatal_failure(wpa_auth, group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004561 return -1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004562 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004563
4564 return 0;
4565}
4566
4567
4568static void wpa_group_sm_step(struct wpa_authenticator *wpa_auth,
4569 struct wpa_group *group)
4570{
4571 if (group->GInit) {
4572 wpa_group_gtk_init(wpa_auth, group);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004573 } else if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) {
4574 /* Do not allow group operations */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004575 } else if (group->wpa_group_state == WPA_GROUP_GTK_INIT &&
4576 group->GTKAuthenticator) {
4577 wpa_group_setkeysdone(wpa_auth, group);
4578 } else if (group->wpa_group_state == WPA_GROUP_SETKEYSDONE &&
4579 group->GTKReKey) {
4580 wpa_group_setkeys(wpa_auth, group);
4581 } else if (group->wpa_group_state == WPA_GROUP_SETKEYS) {
4582 if (group->GKeyDoneStations == 0)
4583 wpa_group_setkeysdone(wpa_auth, group);
4584 else if (group->GTKReKey)
4585 wpa_group_setkeys(wpa_auth, group);
4586 }
4587}
4588
4589
4590static int wpa_sm_step(struct wpa_state_machine *sm)
4591{
Hai Shalomfdcde762020-04-02 11:19:20 -07004592 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004593 return 0;
4594
4595 if (sm->in_step_loop) {
4596 /* This should not happen, but if it does, make sure we do not
4597 * end up freeing the state machine too early by exiting the
4598 * recursive call. */
4599 wpa_printf(MSG_ERROR, "WPA: wpa_sm_step() called recursively");
4600 return 0;
4601 }
4602
4603 sm->in_step_loop = 1;
4604 do {
4605 if (sm->pending_deinit)
4606 break;
4607
Hai Shalome21d4e82020-04-29 16:34:06 -07004608 sm->changed = false;
4609 sm->wpa_auth->group->changed = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004610
4611 SM_STEP_RUN(WPA_PTK);
4612 if (sm->pending_deinit)
4613 break;
4614 SM_STEP_RUN(WPA_PTK_GROUP);
4615 if (sm->pending_deinit)
4616 break;
4617 wpa_group_sm_step(sm->wpa_auth, sm->group);
4618 } while (sm->changed || sm->wpa_auth->group->changed);
4619 sm->in_step_loop = 0;
4620
4621 if (sm->pending_deinit) {
Hai Shalomfdcde762020-04-02 11:19:20 -07004622 wpa_printf(MSG_DEBUG,
4623 "WPA: Completing pending STA state machine deinit for "
4624 MACSTR, MAC2STR(sm->addr));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004625 wpa_free_sta_sm(sm);
4626 return 1;
4627 }
4628 return 0;
4629}
4630
4631
4632static void wpa_sm_call_step(void *eloop_ctx, void *timeout_ctx)
4633{
4634 struct wpa_state_machine *sm = eloop_ctx;
4635 wpa_sm_step(sm);
4636}
4637
4638
4639void wpa_auth_sm_notify(struct wpa_state_machine *sm)
4640{
Hai Shalomfdcde762020-04-02 11:19:20 -07004641 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004642 return;
4643 eloop_register_timeout(0, 0, wpa_sm_call_step, sm, NULL);
4644}
4645
4646
4647void wpa_gtk_rekey(struct wpa_authenticator *wpa_auth)
4648{
4649 int tmp, i;
4650 struct wpa_group *group;
4651
Hai Shalomfdcde762020-04-02 11:19:20 -07004652 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004653 return;
4654
4655 group = wpa_auth->group;
4656
4657 for (i = 0; i < 2; i++) {
4658 tmp = group->GM;
4659 group->GM = group->GN;
4660 group->GN = tmp;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004661 tmp = group->GM_igtk;
4662 group->GM_igtk = group->GN_igtk;
4663 group->GN_igtk = tmp;
Hai Shalomfdcde762020-04-02 11:19:20 -07004664 tmp = group->GM_bigtk;
4665 group->GM_bigtk = group->GN_bigtk;
4666 group->GN_bigtk = tmp;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004667 wpa_gtk_update(wpa_auth, group);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004668 wpa_group_config_group_keys(wpa_auth, group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004669 }
4670}
4671
4672
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004673static const char * wpa_bool_txt(int val)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004674{
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004675 return val ? "TRUE" : "FALSE";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004676}
4677
4678
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004679#define RSN_SUITE "%02x-%02x-%02x-%d"
4680#define RSN_SUITE_ARG(s) \
4681((s) >> 24) & 0xff, ((s) >> 16) & 0xff, ((s) >> 8) & 0xff, (s) & 0xff
4682
4683int wpa_get_mib(struct wpa_authenticator *wpa_auth, char *buf, size_t buflen)
4684{
Hai Shalomfdcde762020-04-02 11:19:20 -07004685 struct wpa_auth_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004686 int len = 0, ret;
4687 char pmkid_txt[PMKID_LEN * 2 + 1];
4688#ifdef CONFIG_RSN_PREAUTH
4689 const int preauth = 1;
4690#else /* CONFIG_RSN_PREAUTH */
4691 const int preauth = 0;
4692#endif /* CONFIG_RSN_PREAUTH */
4693
Hai Shalomfdcde762020-04-02 11:19:20 -07004694 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004695 return len;
Hai Shalomfdcde762020-04-02 11:19:20 -07004696 conf = &wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004697
4698 ret = os_snprintf(buf + len, buflen - len,
4699 "dot11RSNAOptionImplemented=TRUE\n"
4700 "dot11RSNAPreauthenticationImplemented=%s\n"
4701 "dot11RSNAEnabled=%s\n"
4702 "dot11RSNAPreauthenticationEnabled=%s\n",
4703 wpa_bool_txt(preauth),
Hai Shalomfdcde762020-04-02 11:19:20 -07004704 wpa_bool_txt(conf->wpa & WPA_PROTO_RSN),
4705 wpa_bool_txt(conf->rsn_preauth));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004706 if (os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004707 return len;
4708 len += ret;
4709
4710 wpa_snprintf_hex(pmkid_txt, sizeof(pmkid_txt),
4711 wpa_auth->dot11RSNAPMKIDUsed, PMKID_LEN);
4712
4713 ret = os_snprintf(
4714 buf + len, buflen - len,
4715 "dot11RSNAConfigVersion=%u\n"
4716 "dot11RSNAConfigPairwiseKeysSupported=9999\n"
4717 /* FIX: dot11RSNAConfigGroupCipher */
4718 /* FIX: dot11RSNAConfigGroupRekeyMethod */
4719 /* FIX: dot11RSNAConfigGroupRekeyTime */
4720 /* FIX: dot11RSNAConfigGroupRekeyPackets */
4721 "dot11RSNAConfigGroupRekeyStrict=%u\n"
4722 "dot11RSNAConfigGroupUpdateCount=%u\n"
4723 "dot11RSNAConfigPairwiseUpdateCount=%u\n"
4724 "dot11RSNAConfigGroupCipherSize=%u\n"
4725 "dot11RSNAConfigPMKLifetime=%u\n"
4726 "dot11RSNAConfigPMKReauthThreshold=%u\n"
4727 "dot11RSNAConfigNumberOfPTKSAReplayCounters=0\n"
4728 "dot11RSNAConfigSATimeout=%u\n"
4729 "dot11RSNAAuthenticationSuiteSelected=" RSN_SUITE "\n"
4730 "dot11RSNAPairwiseCipherSelected=" RSN_SUITE "\n"
4731 "dot11RSNAGroupCipherSelected=" RSN_SUITE "\n"
4732 "dot11RSNAPMKIDUsed=%s\n"
4733 "dot11RSNAAuthenticationSuiteRequested=" RSN_SUITE "\n"
4734 "dot11RSNAPairwiseCipherRequested=" RSN_SUITE "\n"
4735 "dot11RSNAGroupCipherRequested=" RSN_SUITE "\n"
4736 "dot11RSNATKIPCounterMeasuresInvoked=%u\n"
4737 "dot11RSNA4WayHandshakeFailures=%u\n"
4738 "dot11RSNAConfigNumberOfGTKSAReplayCounters=0\n",
4739 RSN_VERSION,
Hai Shalomfdcde762020-04-02 11:19:20 -07004740 !!conf->wpa_strict_rekey,
4741 conf->wpa_group_update_count,
4742 conf->wpa_pairwise_update_count,
4743 wpa_cipher_key_len(conf->wpa_group) * 8,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004744 dot11RSNAConfigPMKLifetime,
4745 dot11RSNAConfigPMKReauthThreshold,
4746 dot11RSNAConfigSATimeout,
4747 RSN_SUITE_ARG(wpa_auth->dot11RSNAAuthenticationSuiteSelected),
4748 RSN_SUITE_ARG(wpa_auth->dot11RSNAPairwiseCipherSelected),
4749 RSN_SUITE_ARG(wpa_auth->dot11RSNAGroupCipherSelected),
4750 pmkid_txt,
4751 RSN_SUITE_ARG(wpa_auth->dot11RSNAAuthenticationSuiteRequested),
4752 RSN_SUITE_ARG(wpa_auth->dot11RSNAPairwiseCipherRequested),
4753 RSN_SUITE_ARG(wpa_auth->dot11RSNAGroupCipherRequested),
4754 wpa_auth->dot11RSNATKIPCounterMeasuresInvoked,
4755 wpa_auth->dot11RSNA4WayHandshakeFailures);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004756 if (os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004757 return len;
4758 len += ret;
4759
4760 /* TODO: dot11RSNAConfigPairwiseCiphersTable */
4761 /* TODO: dot11RSNAConfigAuthenticationSuitesTable */
4762
4763 /* Private MIB */
4764 ret = os_snprintf(buf + len, buflen - len, "hostapdWPAGroupState=%d\n",
4765 wpa_auth->group->wpa_group_state);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004766 if (os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004767 return len;
4768 len += ret;
4769
4770 return len;
4771}
4772
4773
4774int wpa_get_mib_sta(struct wpa_state_machine *sm, char *buf, size_t buflen)
4775{
4776 int len = 0, ret;
4777 u32 pairwise = 0;
4778
Hai Shalomfdcde762020-04-02 11:19:20 -07004779 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004780 return 0;
4781
4782 /* TODO: FF-FF-FF-FF-FF-FF entry for broadcast/multicast stats */
4783
4784 /* dot11RSNAStatsEntry */
4785
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07004786 pairwise = wpa_cipher_to_suite(sm->wpa == WPA_VERSION_WPA2 ?
4787 WPA_PROTO_RSN : WPA_PROTO_WPA,
4788 sm->pairwise);
4789 if (pairwise == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004790 return 0;
4791
4792 ret = os_snprintf(
4793 buf + len, buflen - len,
4794 /* TODO: dot11RSNAStatsIndex */
4795 "dot11RSNAStatsSTAAddress=" MACSTR "\n"
4796 "dot11RSNAStatsVersion=1\n"
4797 "dot11RSNAStatsSelectedPairwiseCipher=" RSN_SUITE "\n"
4798 /* TODO: dot11RSNAStatsTKIPICVErrors */
4799 "dot11RSNAStatsTKIPLocalMICFailures=%u\n"
4800 "dot11RSNAStatsTKIPRemoteMICFailures=%u\n"
4801 /* TODO: dot11RSNAStatsCCMPReplays */
4802 /* TODO: dot11RSNAStatsCCMPDecryptErrors */
4803 /* TODO: dot11RSNAStatsTKIPReplays */,
4804 MAC2STR(sm->addr),
4805 RSN_SUITE_ARG(pairwise),
4806 sm->dot11RSNAStatsTKIPLocalMICFailures,
4807 sm->dot11RSNAStatsTKIPRemoteMICFailures);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004808 if (os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004809 return len;
4810 len += ret;
4811
4812 /* Private MIB */
4813 ret = os_snprintf(buf + len, buflen - len,
Hai Shalomc3565922019-10-28 11:58:20 -07004814 "wpa=%d\n"
4815 "AKMSuiteSelector=" RSN_SUITE "\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004816 "hostapdWPAPTKState=%d\n"
4817 "hostapdWPAPTKGroupState=%d\n",
Hai Shalomc3565922019-10-28 11:58:20 -07004818 sm->wpa,
4819 RSN_SUITE_ARG(wpa_akm_to_suite(sm->wpa_key_mgmt)),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004820 sm->wpa_ptk_state,
4821 sm->wpa_ptk_group_state);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004822 if (os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004823 return len;
4824 len += ret;
4825
4826 return len;
4827}
4828
4829
4830void wpa_auth_countermeasures_start(struct wpa_authenticator *wpa_auth)
4831{
4832 if (wpa_auth)
4833 wpa_auth->dot11RSNATKIPCounterMeasuresInvoked++;
4834}
4835
4836
4837int wpa_auth_pairwise_set(struct wpa_state_machine *sm)
4838{
4839 return sm && sm->pairwise_set;
4840}
4841
4842
4843int wpa_auth_get_pairwise(struct wpa_state_machine *sm)
4844{
4845 return sm->pairwise;
4846}
4847
4848
Hai Shalom74f70d42019-02-11 14:42:39 -08004849const u8 * wpa_auth_get_pmk(struct wpa_state_machine *sm, int *len)
4850{
4851 if (!sm)
4852 return NULL;
4853 *len = sm->pmk_len;
4854 return sm->PMK;
4855}
4856
4857
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004858int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm)
4859{
Hai Shalomfdcde762020-04-02 11:19:20 -07004860 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004861 return -1;
4862 return sm->wpa_key_mgmt;
4863}
4864
4865
4866int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm)
4867{
Hai Shalomfdcde762020-04-02 11:19:20 -07004868 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004869 return 0;
4870 return sm->wpa;
4871}
4872
4873
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02004874int wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm)
4875{
4876 if (!sm || !wpa_key_mgmt_ft(sm->wpa_key_mgmt))
4877 return 0;
4878 return sm->tk_already_set;
4879}
4880
4881
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004882int wpa_auth_sta_fils_tk_already_set(struct wpa_state_machine *sm)
4883{
4884 if (!sm || !wpa_key_mgmt_fils(sm->wpa_key_mgmt))
4885 return 0;
4886 return sm->tk_already_set;
4887}
4888
4889
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004890int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm,
4891 struct rsn_pmksa_cache_entry *entry)
4892{
Hai Shalomfdcde762020-04-02 11:19:20 -07004893 if (!sm || sm->pmksa != entry)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004894 return -1;
4895 sm->pmksa = NULL;
4896 return 0;
4897}
4898
4899
4900struct rsn_pmksa_cache_entry *
4901wpa_auth_sta_get_pmksa(struct wpa_state_machine *sm)
4902{
4903 return sm ? sm->pmksa : NULL;
4904}
4905
4906
4907void wpa_auth_sta_local_mic_failure_report(struct wpa_state_machine *sm)
4908{
4909 if (sm)
4910 sm->dot11RSNAStatsTKIPLocalMICFailures++;
4911}
4912
4913
4914const u8 * wpa_auth_get_wpa_ie(struct wpa_authenticator *wpa_auth, size_t *len)
4915{
Hai Shalomfdcde762020-04-02 11:19:20 -07004916 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004917 return NULL;
4918 *len = wpa_auth->wpa_ie_len;
4919 return wpa_auth->wpa_ie;
4920}
4921
4922
4923int wpa_auth_pmksa_add(struct wpa_state_machine *sm, const u8 *pmk,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004924 unsigned int pmk_len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004925 int session_timeout, struct eapol_state_machine *eapol)
4926{
Hai Shalomfdcde762020-04-02 11:19:20 -07004927 if (!sm || sm->wpa != WPA_VERSION_WPA2 ||
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07004928 sm->wpa_auth->conf.disable_pmksa_caching)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004929 return -1;
4930
Hai Shalom81f62d82019-07-22 12:10:00 -07004931#ifdef CONFIG_IEEE80211R_AP
4932 if (pmk_len >= 2 * PMK_LEN && wpa_key_mgmt_ft(sm->wpa_key_mgmt) &&
4933 wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) &&
4934 !wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) {
4935 /* Cache MPMK/XXKey instead of initial part from MSK */
4936 pmk = pmk + PMK_LEN;
4937 pmk_len = PMK_LEN;
4938 } else
4939#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004940 if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004941 if (pmk_len > PMK_LEN_SUITE_B_192)
4942 pmk_len = PMK_LEN_SUITE_B_192;
4943 } else if (pmk_len > PMK_LEN) {
4944 pmk_len = PMK_LEN;
4945 }
4946
Hai Shalom81f62d82019-07-22 12:10:00 -07004947 wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK", pmk, pmk_len);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004948 if (pmksa_cache_auth_add(sm->wpa_auth->pmksa, pmk, pmk_len, NULL,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004949 sm->PTK.kck, sm->PTK.kck_len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004950 sm->wpa_auth->addr, sm->addr, session_timeout,
4951 eapol, sm->wpa_key_mgmt))
4952 return 0;
4953
4954 return -1;
4955}
4956
4957
4958int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth,
4959 const u8 *pmk, size_t len, const u8 *sta_addr,
4960 int session_timeout,
4961 struct eapol_state_machine *eapol)
4962{
Hai Shalomfdcde762020-04-02 11:19:20 -07004963 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004964 return -1;
4965
Hai Shalom81f62d82019-07-22 12:10:00 -07004966 wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK from preauth", pmk, len);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004967 if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, len, NULL,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004968 NULL, 0,
4969 wpa_auth->addr,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004970 sta_addr, session_timeout, eapol,
4971 WPA_KEY_MGMT_IEEE8021X))
4972 return 0;
4973
4974 return -1;
4975}
4976
4977
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004978int wpa_auth_pmksa_add_sae(struct wpa_authenticator *wpa_auth, const u8 *addr,
Sunil Ravi89eba102022-09-13 21:04:37 -07004979 const u8 *pmk, size_t pmk_len, const u8 *pmkid,
4980 int akmp)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004981{
4982 if (wpa_auth->conf.disable_pmksa_caching)
4983 return -1;
4984
Sunil Ravi89eba102022-09-13 21:04:37 -07004985 wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK from SAE", pmk, pmk_len);
4986 if (!akmp)
4987 akmp = WPA_KEY_MGMT_SAE;
4988 if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, pmk_len, pmkid,
4989 NULL, 0, wpa_auth->addr, addr, 0, NULL, akmp))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004990 return 0;
4991
4992 return -1;
4993}
4994
4995
Roshan Pius3a1667e2018-07-03 15:17:14 -07004996void wpa_auth_add_sae_pmkid(struct wpa_state_machine *sm, const u8 *pmkid)
4997{
4998 os_memcpy(sm->pmkid, pmkid, PMKID_LEN);
4999 sm->pmkid_set = 1;
5000}
5001
5002
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005003int wpa_auth_pmksa_add2(struct wpa_authenticator *wpa_auth, const u8 *addr,
5004 const u8 *pmk, size_t pmk_len, const u8 *pmkid,
5005 int session_timeout, int akmp)
5006{
Hai Shaloma20dcd72022-02-04 13:43:00 -08005007 if (!wpa_auth || wpa_auth->conf.disable_pmksa_caching)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005008 return -1;
5009
Hai Shalom81f62d82019-07-22 12:10:00 -07005010 wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK (2)", pmk, PMK_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005011 if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, pmk_len, pmkid,
5012 NULL, 0, wpa_auth->addr, addr, session_timeout,
5013 NULL, akmp))
5014 return 0;
5015
5016 return -1;
5017}
5018
5019
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07005020void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth,
5021 const u8 *sta_addr)
5022{
5023 struct rsn_pmksa_cache_entry *pmksa;
5024
Hai Shalomfdcde762020-04-02 11:19:20 -07005025 if (!wpa_auth || !wpa_auth->pmksa)
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07005026 return;
5027 pmksa = pmksa_cache_auth_get(wpa_auth->pmksa, sta_addr, NULL);
5028 if (pmksa) {
5029 wpa_printf(MSG_DEBUG, "WPA: Remove PMKSA cache entry for "
5030 MACSTR " based on request", MAC2STR(sta_addr));
5031 pmksa_cache_free_entry(wpa_auth->pmksa, pmksa);
5032 }
5033}
5034
5035
Dmitry Shmidte4663042016-04-04 10:07:49 -07005036int wpa_auth_pmksa_list(struct wpa_authenticator *wpa_auth, char *buf,
5037 size_t len)
5038{
5039 if (!wpa_auth || !wpa_auth->pmksa)
5040 return 0;
5041 return pmksa_cache_auth_list(wpa_auth->pmksa, buf, len);
5042}
5043
5044
5045void wpa_auth_pmksa_flush(struct wpa_authenticator *wpa_auth)
5046{
5047 if (wpa_auth && wpa_auth->pmksa)
5048 pmksa_cache_auth_flush(wpa_auth->pmksa);
5049}
5050
5051
Paul Stewart092955c2017-02-06 09:13:09 -08005052#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
5053#ifdef CONFIG_MESH
5054
5055int wpa_auth_pmksa_list_mesh(struct wpa_authenticator *wpa_auth, const u8 *addr,
5056 char *buf, size_t len)
5057{
5058 if (!wpa_auth || !wpa_auth->pmksa)
5059 return 0;
5060
5061 return pmksa_cache_auth_list_mesh(wpa_auth->pmksa, addr, buf, len);
5062}
5063
5064
5065struct rsn_pmksa_cache_entry *
5066wpa_auth_pmksa_create_entry(const u8 *aa, const u8 *spa, const u8 *pmk,
Sunil Ravi89eba102022-09-13 21:04:37 -07005067 size_t pmk_len, int akmp,
Paul Stewart092955c2017-02-06 09:13:09 -08005068 const u8 *pmkid, int expiration)
5069{
5070 struct rsn_pmksa_cache_entry *entry;
5071 struct os_reltime now;
5072
Sunil Ravi89eba102022-09-13 21:04:37 -07005073 entry = pmksa_cache_auth_create_entry(pmk, pmk_len, pmkid, NULL, 0, aa,
5074 spa, 0, NULL, akmp);
Paul Stewart092955c2017-02-06 09:13:09 -08005075 if (!entry)
5076 return NULL;
5077
5078 os_get_reltime(&now);
5079 entry->expiration = now.sec + expiration;
5080 return entry;
5081}
5082
5083
5084int wpa_auth_pmksa_add_entry(struct wpa_authenticator *wpa_auth,
5085 struct rsn_pmksa_cache_entry *entry)
5086{
5087 int ret;
5088
5089 if (!wpa_auth || !wpa_auth->pmksa)
5090 return -1;
5091
5092 ret = pmksa_cache_auth_add_entry(wpa_auth->pmksa, entry);
5093 if (ret < 0)
5094 wpa_printf(MSG_DEBUG,
5095 "RSN: Failed to store external PMKSA cache for "
5096 MACSTR, MAC2STR(entry->spa));
5097
5098 return ret;
5099}
5100
5101#endif /* CONFIG_MESH */
5102#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
5103
5104
Dmitry Shmidte4663042016-04-04 10:07:49 -07005105struct rsn_pmksa_cache_entry *
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005106wpa_auth_pmksa_get(struct wpa_authenticator *wpa_auth, const u8 *sta_addr,
5107 const u8 *pmkid)
Dmitry Shmidte4663042016-04-04 10:07:49 -07005108{
5109 if (!wpa_auth || !wpa_auth->pmksa)
5110 return NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005111 return pmksa_cache_auth_get(wpa_auth->pmksa, sta_addr, pmkid);
Dmitry Shmidte4663042016-04-04 10:07:49 -07005112}
5113
5114
5115void wpa_auth_pmksa_set_to_sm(struct rsn_pmksa_cache_entry *pmksa,
5116 struct wpa_state_machine *sm,
5117 struct wpa_authenticator *wpa_auth,
5118 u8 *pmkid, u8 *pmk)
5119{
5120 if (!sm)
5121 return;
5122
5123 sm->pmksa = pmksa;
5124 os_memcpy(pmk, pmksa->pmk, PMK_LEN);
5125 os_memcpy(pmkid, pmksa->pmkid, PMKID_LEN);
5126 os_memcpy(wpa_auth->dot11RSNAPMKIDUsed, pmksa->pmkid, PMKID_LEN);
5127}
5128
5129
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005130/*
5131 * Remove and free the group from wpa_authenticator. This is triggered by a
5132 * callback to make sure nobody is currently iterating the group list while it
5133 * gets modified.
5134 */
5135static void wpa_group_free(struct wpa_authenticator *wpa_auth,
5136 struct wpa_group *group)
5137{
5138 struct wpa_group *prev = wpa_auth->group;
5139
5140 wpa_printf(MSG_DEBUG, "WPA: Remove group state machine for VLAN-ID %d",
5141 group->vlan_id);
5142
5143 while (prev) {
5144 if (prev->next == group) {
5145 /* This never frees the special first group as needed */
5146 prev->next = group->next;
5147 os_free(group);
5148 break;
5149 }
5150 prev = prev->next;
5151 }
5152
5153}
5154
5155
5156/* Increase the reference counter for group */
5157static void wpa_group_get(struct wpa_authenticator *wpa_auth,
5158 struct wpa_group *group)
5159{
5160 /* Skip the special first group */
5161 if (wpa_auth->group == group)
5162 return;
5163
5164 group->references++;
5165}
5166
5167
5168/* Decrease the reference counter and maybe free the group */
5169static void wpa_group_put(struct wpa_authenticator *wpa_auth,
5170 struct wpa_group *group)
5171{
5172 /* Skip the special first group */
5173 if (wpa_auth->group == group)
5174 return;
5175
5176 group->references--;
5177 if (group->references)
5178 return;
5179 wpa_group_free(wpa_auth, group);
5180}
5181
5182
5183/*
5184 * Add a group that has its references counter set to zero. Caller needs to
5185 * call wpa_group_get() on the return value to mark the entry in use.
5186 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005187static struct wpa_group *
5188wpa_auth_add_group(struct wpa_authenticator *wpa_auth, int vlan_id)
5189{
5190 struct wpa_group *group;
5191
Hai Shalomfdcde762020-04-02 11:19:20 -07005192 if (!wpa_auth || !wpa_auth->group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005193 return NULL;
5194
5195 wpa_printf(MSG_DEBUG, "WPA: Add group state machine for VLAN-ID %d",
5196 vlan_id);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005197 group = wpa_group_init(wpa_auth, vlan_id, 0);
Hai Shalomfdcde762020-04-02 11:19:20 -07005198 if (!group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005199 return NULL;
5200
5201 group->next = wpa_auth->group->next;
5202 wpa_auth->group->next = group;
5203
5204 return group;
5205}
5206
5207
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005208/*
5209 * Enforce that the group state machine for the VLAN is running, increase
5210 * reference counter as interface is up. References might have been increased
5211 * even if a negative value is returned.
5212 * Returns: -1 on error (group missing, group already failed); otherwise, 0
5213 */
5214int wpa_auth_ensure_group(struct wpa_authenticator *wpa_auth, int vlan_id)
5215{
5216 struct wpa_group *group;
5217
Hai Shalomfdcde762020-04-02 11:19:20 -07005218 if (!wpa_auth)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005219 return 0;
5220
5221 group = wpa_auth->group;
5222 while (group) {
5223 if (group->vlan_id == vlan_id)
5224 break;
5225 group = group->next;
5226 }
5227
Hai Shalomfdcde762020-04-02 11:19:20 -07005228 if (!group) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005229 group = wpa_auth_add_group(wpa_auth, vlan_id);
Hai Shalomfdcde762020-04-02 11:19:20 -07005230 if (!group)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005231 return -1;
5232 }
5233
5234 wpa_printf(MSG_DEBUG,
5235 "WPA: Ensure group state machine running for VLAN ID %d",
5236 vlan_id);
5237
5238 wpa_group_get(wpa_auth, group);
5239 group->num_setup_iface++;
5240
5241 if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
5242 return -1;
5243
5244 return 0;
5245}
5246
5247
5248/*
5249 * Decrease reference counter, expected to be zero afterwards.
5250 * returns: -1 on error (group not found, group in fail state)
5251 * -2 if wpa_group is still referenced
5252 * 0 else
5253 */
5254int wpa_auth_release_group(struct wpa_authenticator *wpa_auth, int vlan_id)
5255{
5256 struct wpa_group *group;
5257 int ret = 0;
5258
Hai Shalomfdcde762020-04-02 11:19:20 -07005259 if (!wpa_auth)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005260 return 0;
5261
5262 group = wpa_auth->group;
5263 while (group) {
5264 if (group->vlan_id == vlan_id)
5265 break;
5266 group = group->next;
5267 }
5268
Hai Shalomfdcde762020-04-02 11:19:20 -07005269 if (!group)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005270 return -1;
5271
5272 wpa_printf(MSG_DEBUG,
5273 "WPA: Try stopping group state machine for VLAN ID %d",
5274 vlan_id);
5275
5276 if (group->num_setup_iface <= 0) {
5277 wpa_printf(MSG_ERROR,
5278 "WPA: wpa_auth_release_group called more often than wpa_auth_ensure_group for VLAN ID %d, skipping.",
5279 vlan_id);
5280 return -1;
5281 }
5282 group->num_setup_iface--;
5283
5284 if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
5285 ret = -1;
5286
5287 if (group->references > 1) {
5288 wpa_printf(MSG_DEBUG,
5289 "WPA: Cannot stop group state machine for VLAN ID %d as references are still hold",
5290 vlan_id);
5291 ret = -2;
5292 }
5293
5294 wpa_group_put(wpa_auth, group);
5295
5296 return ret;
5297}
5298
5299
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005300int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id)
5301{
5302 struct wpa_group *group;
5303
Hai Shalomfdcde762020-04-02 11:19:20 -07005304 if (!sm || !sm->wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005305 return 0;
5306
5307 group = sm->wpa_auth->group;
5308 while (group) {
5309 if (group->vlan_id == vlan_id)
5310 break;
5311 group = group->next;
5312 }
5313
Hai Shalomfdcde762020-04-02 11:19:20 -07005314 if (!group) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005315 group = wpa_auth_add_group(sm->wpa_auth, vlan_id);
Hai Shalomfdcde762020-04-02 11:19:20 -07005316 if (!group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005317 return -1;
5318 }
5319
5320 if (sm->group == group)
5321 return 0;
5322
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005323 if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
5324 return -1;
5325
Hai Shalomfdcde762020-04-02 11:19:20 -07005326 wpa_printf(MSG_DEBUG, "WPA: Moving STA " MACSTR
5327 " to use group state machine for VLAN ID %d",
5328 MAC2STR(sm->addr), vlan_id);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005329
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005330 wpa_group_get(sm->wpa_auth, group);
5331 wpa_group_put(sm->wpa_auth, sm->group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005332 sm->group = group;
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005333
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005334 return 0;
5335}
5336
5337
5338void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth,
5339 struct wpa_state_machine *sm, int ack)
5340{
Hai Shalomfdcde762020-04-02 11:19:20 -07005341 if (!wpa_auth || !sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005342 return;
5343 wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key TX status for STA " MACSTR
5344 " ack=%d", MAC2STR(sm->addr), ack);
5345 if (sm->pending_1_of_4_timeout && ack) {
5346 /*
5347 * Some deployed supplicant implementations update their SNonce
5348 * for each EAPOL-Key 2/4 message even within the same 4-way
5349 * handshake and then fail to use the first SNonce when
5350 * deriving the PTK. This results in unsuccessful 4-way
5351 * handshake whenever the relatively short initial timeout is
5352 * reached and EAPOL-Key 1/4 is retransmitted. Try to work
5353 * around this by increasing the timeout now that we know that
5354 * the station has received the frame.
5355 */
5356 int timeout_ms = eapol_key_timeout_subseq;
Hai Shalomfdcde762020-04-02 11:19:20 -07005357 wpa_printf(MSG_DEBUG,
5358 "WPA: Increase initial EAPOL-Key 1/4 timeout by %u ms because of acknowledged frame",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005359 timeout_ms);
5360 eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm);
5361 eloop_register_timeout(timeout_ms / 1000,
5362 (timeout_ms % 1000) * 1000,
5363 wpa_send_eapol_timeout, wpa_auth, sm);
5364 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005365
5366#ifdef CONFIG_TESTING_OPTIONS
5367 if (sm->eapol_status_cb) {
5368 sm->eapol_status_cb(sm->eapol_status_cb_ctx1,
5369 sm->eapol_status_cb_ctx2);
5370 sm->eapol_status_cb = NULL;
5371 }
5372#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005373}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005374
5375
5376int wpa_auth_uses_sae(struct wpa_state_machine *sm)
5377{
Hai Shalomfdcde762020-04-02 11:19:20 -07005378 if (!sm)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005379 return 0;
5380 return wpa_key_mgmt_sae(sm->wpa_key_mgmt);
5381}
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005382
5383
5384int wpa_auth_uses_ft_sae(struct wpa_state_machine *sm)
5385{
Hai Shalomfdcde762020-04-02 11:19:20 -07005386 if (!sm)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005387 return 0;
Sunil Ravi89eba102022-09-13 21:04:37 -07005388 return sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_SAE ||
5389 sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_SAE_EXT_KEY;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005390}
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08005391
5392
5393#ifdef CONFIG_P2P
5394int wpa_auth_get_ip_addr(struct wpa_state_machine *sm, u8 *addr)
5395{
Hai Shalomfdcde762020-04-02 11:19:20 -07005396 if (!sm || WPA_GET_BE32(sm->ip_addr) == 0)
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08005397 return -1;
5398 os_memcpy(addr, sm->ip_addr, 4);
5399 return 0;
5400}
5401#endif /* CONFIG_P2P */
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08005402
5403
5404int wpa_auth_radius_das_disconnect_pmksa(struct wpa_authenticator *wpa_auth,
5405 struct radius_das_attrs *attr)
5406{
5407 return pmksa_cache_auth_radius_das_disconnect(wpa_auth->pmksa, attr);
5408}
Dmitry Shmidt7f656022015-02-25 14:36:37 -08005409
5410
5411void wpa_auth_reconfig_group_keys(struct wpa_authenticator *wpa_auth)
5412{
5413 struct wpa_group *group;
5414
5415 if (!wpa_auth)
5416 return;
5417 for (group = wpa_auth->group; group; group = group->next)
5418 wpa_group_config_group_keys(wpa_auth, group);
5419}
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005420
5421
5422#ifdef CONFIG_FILS
5423
5424struct wpa_auth_fils_iter_data {
5425 struct wpa_authenticator *auth;
5426 const u8 *cache_id;
5427 struct rsn_pmksa_cache_entry *pmksa;
5428 const u8 *spa;
5429 const u8 *pmkid;
5430};
5431
5432
5433static int wpa_auth_fils_iter(struct wpa_authenticator *a, void *ctx)
5434{
5435 struct wpa_auth_fils_iter_data *data = ctx;
5436
5437 if (a == data->auth || !a->conf.fils_cache_id_set ||
5438 os_memcmp(a->conf.fils_cache_id, data->cache_id,
5439 FILS_CACHE_ID_LEN) != 0)
5440 return 0;
5441 data->pmksa = pmksa_cache_auth_get(a->pmksa, data->spa, data->pmkid);
5442 return data->pmksa != NULL;
5443}
5444
5445
5446struct rsn_pmksa_cache_entry *
5447wpa_auth_pmksa_get_fils_cache_id(struct wpa_authenticator *wpa_auth,
5448 const u8 *sta_addr, const u8 *pmkid)
5449{
5450 struct wpa_auth_fils_iter_data idata;
5451
5452 if (!wpa_auth->conf.fils_cache_id_set)
5453 return NULL;
5454 idata.auth = wpa_auth;
5455 idata.cache_id = wpa_auth->conf.fils_cache_id;
5456 idata.pmksa = NULL;
5457 idata.spa = sta_addr;
5458 idata.pmkid = pmkid;
5459 wpa_auth_for_each_auth(wpa_auth, wpa_auth_fils_iter, &idata);
5460 return idata.pmksa;
5461}
5462
5463
5464#ifdef CONFIG_IEEE80211R_AP
Roshan Pius3a1667e2018-07-03 15:17:14 -07005465int wpa_auth_write_fte(struct wpa_authenticator *wpa_auth, int use_sha384,
5466 u8 *buf, size_t len)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005467{
5468 struct wpa_auth_config *conf = &wpa_auth->conf;
5469
Roshan Pius3a1667e2018-07-03 15:17:14 -07005470 return wpa_write_ftie(conf, use_sha384, conf->r0_key_holder,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005471 conf->r0_key_holder_len,
Hai Shalomfdcde762020-04-02 11:19:20 -07005472 NULL, NULL, buf, len, NULL, 0, 0);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005473}
5474#endif /* CONFIG_IEEE80211R_AP */
5475
5476
5477void wpa_auth_get_fils_aead_params(struct wpa_state_machine *sm,
5478 u8 *fils_anonce, u8 *fils_snonce,
5479 u8 *fils_kek, size_t *fils_kek_len)
5480{
5481 os_memcpy(fils_anonce, sm->ANonce, WPA_NONCE_LEN);
5482 os_memcpy(fils_snonce, sm->SNonce, WPA_NONCE_LEN);
5483 os_memcpy(fils_kek, sm->PTK.kek, WPA_KEK_MAX_LEN);
5484 *fils_kek_len = sm->PTK.kek_len;
5485}
5486
Hai Shalom81f62d82019-07-22 12:10:00 -07005487
5488void wpa_auth_add_fils_pmk_pmkid(struct wpa_state_machine *sm, const u8 *pmk,
5489 size_t pmk_len, const u8 *pmkid)
5490{
5491 os_memcpy(sm->PMK, pmk, pmk_len);
5492 sm->pmk_len = pmk_len;
5493 os_memcpy(sm->pmkid, pmkid, PMKID_LEN);
5494 sm->pmkid_set = 1;
5495}
5496
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005497#endif /* CONFIG_FILS */
5498
5499
Hai Shalom021b0b52019-04-10 11:17:58 -07005500void wpa_auth_set_auth_alg(struct wpa_state_machine *sm, u16 auth_alg)
5501{
5502 if (sm)
5503 sm->auth_alg = auth_alg;
5504}
5505
5506
5507#ifdef CONFIG_DPP2
5508void wpa_auth_set_dpp_z(struct wpa_state_machine *sm, const struct wpabuf *z)
5509{
5510 if (sm) {
5511 wpabuf_clear_free(sm->dpp_z);
5512 sm->dpp_z = z ? wpabuf_dup(z) : NULL;
5513 }
5514}
5515#endif /* CONFIG_DPP2 */
5516
5517
Hai Shalom899fcc72020-10-19 14:38:18 -07005518void wpa_auth_set_transition_disable(struct wpa_authenticator *wpa_auth,
5519 u8 val)
5520{
5521 if (wpa_auth)
5522 wpa_auth->conf.transition_disable = val;
5523}
5524
5525
Roshan Pius3a1667e2018-07-03 15:17:14 -07005526#ifdef CONFIG_TESTING_OPTIONS
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005527
5528int wpa_auth_resend_m1(struct wpa_state_machine *sm, int change_anonce,
5529 void (*cb)(void *ctx1, void *ctx2),
5530 void *ctx1, void *ctx2)
5531{
5532 const u8 *anonce = sm->ANonce;
5533 u8 anonce_buf[WPA_NONCE_LEN];
5534
5535 if (change_anonce) {
5536 if (random_get_bytes(anonce_buf, WPA_NONCE_LEN))
5537 return -1;
5538 anonce = anonce_buf;
5539 }
5540
5541 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
5542 "sending 1/4 msg of 4-Way Handshake (TESTING)");
5543 wpa_send_eapol(sm->wpa_auth, sm,
5544 WPA_KEY_INFO_ACK | WPA_KEY_INFO_KEY_TYPE, NULL,
5545 anonce, NULL, 0, 0, 0);
5546 return 0;
5547}
5548
5549
5550int wpa_auth_resend_m3(struct wpa_state_machine *sm,
5551 void (*cb)(void *ctx1, void *ctx2),
5552 void *ctx1, void *ctx2)
5553{
Roshan Pius3a1667e2018-07-03 15:17:14 -07005554 u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde, *pos;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005555 u8 *opos;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005556 size_t gtk_len, kde_len;
Hai Shalom899fcc72020-10-19 14:38:18 -07005557 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005558 struct wpa_group *gsm = sm->group;
5559 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07005560 int wpa_ie_len, secure, gtkidx, encr = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07005561 u8 hdr[2];
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005562
5563 /* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, [MDIE],
Hai Shalomfdcde762020-04-02 11:19:20 -07005564 GTK[GN], IGTK, [BIGTK], [FTIE], [TIE * 2])
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005565 */
5566
5567 /* Use 0 RSC */
5568 os_memset(rsc, 0, WPA_KEY_RSC_LEN);
5569 /* If FT is used, wpa_auth->wpa_ie includes both RSNIE and MDIE */
5570 wpa_ie = sm->wpa_auth->wpa_ie;
5571 wpa_ie_len = sm->wpa_auth->wpa_ie_len;
5572 if (sm->wpa == WPA_VERSION_WPA &&
5573 (sm->wpa_auth->conf.wpa & WPA_PROTO_RSN) &&
5574 wpa_ie_len > wpa_ie[1] + 2 && wpa_ie[0] == WLAN_EID_RSN) {
5575 /* WPA-only STA, remove RSN IE and possible MDIE */
5576 wpa_ie = wpa_ie + wpa_ie[1] + 2;
Hai Shalom60840252021-02-19 19:02:11 -08005577 if (wpa_ie[0] == WLAN_EID_RSNX)
5578 wpa_ie = wpa_ie + wpa_ie[1] + 2;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005579 if (wpa_ie[0] == WLAN_EID_MOBILITY_DOMAIN)
5580 wpa_ie = wpa_ie + wpa_ie[1] + 2;
5581 wpa_ie_len = wpa_ie[1] + 2;
5582 }
5583 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
5584 "sending 3/4 msg of 4-Way Handshake (TESTING)");
5585 if (sm->wpa == WPA_VERSION_WPA2) {
5586 /* WPA2 send GTK in the 4-way handshake */
5587 secure = 1;
5588 gtk = gsm->GTK[gsm->GN - 1];
5589 gtk_len = gsm->GTK_len;
Hai Shalomc3565922019-10-28 11:58:20 -07005590 gtkidx = gsm->GN;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005591 _rsc = rsc;
5592 encr = 1;
5593 } else {
5594 /* WPA does not include GTK in msg 3/4 */
5595 secure = 0;
5596 gtk = NULL;
5597 gtk_len = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005598 _rsc = NULL;
5599 if (sm->rx_eapol_key_secure) {
5600 /*
5601 * It looks like Windows 7 supplicant tries to use
5602 * Secure bit in msg 2/4 after having reported Michael
5603 * MIC failure and it then rejects the 4-way handshake
5604 * if msg 3/4 does not set Secure bit. Work around this
5605 * by setting the Secure bit here even in the case of
5606 * WPA if the supplicant used it first.
5607 */
5608 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07005609 "STA used Secure bit in WPA msg 2/4 - set Secure for 3/4 as workaround");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005610 secure = 1;
5611 }
5612 }
5613
Hai Shalom74f70d42019-02-11 14:42:39 -08005614 kde_len = wpa_ie_len + ieee80211w_kde_len(sm) + ocv_oci_len(sm);
Hai Shalomfdcde762020-04-02 11:19:20 -07005615
5616 if (sm->use_ext_key_id)
5617 kde_len += 2 + RSN_SELECTOR_LEN + 2;
5618
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005619 if (gtk)
5620 kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len;
5621#ifdef CONFIG_IEEE80211R_AP
5622 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
5623 kde_len += 2 + PMKID_LEN; /* PMKR1Name into RSN IE */
5624 kde_len += 300; /* FTIE + 2 * TIE */
5625 }
5626#endif /* CONFIG_IEEE80211R_AP */
5627 kde = os_malloc(kde_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07005628 if (!kde)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005629 return -1;
5630
5631 pos = kde;
5632 os_memcpy(pos, wpa_ie, wpa_ie_len);
5633 pos += wpa_ie_len;
5634#ifdef CONFIG_IEEE80211R_AP
5635 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
5636 int res;
5637 size_t elen;
5638
5639 elen = pos - kde;
5640 res = wpa_insert_pmkid(kde, &elen, sm->pmk_r1_name);
5641 if (res < 0) {
Hai Shalomfdcde762020-04-02 11:19:20 -07005642 wpa_printf(MSG_ERROR,
5643 "FT: Failed to insert PMKR1Name into RSN IE in EAPOL-Key data");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005644 os_free(kde);
5645 return -1;
5646 }
5647 pos -= wpa_ie_len;
5648 pos += elen;
5649 }
5650#endif /* CONFIG_IEEE80211R_AP */
Hai Shalomfdcde762020-04-02 11:19:20 -07005651 hdr[1] = 0;
5652
5653 if (sm->use_ext_key_id) {
5654 hdr[0] = sm->keyidx_active & 0x01;
5655 pos = wpa_add_kde(pos, RSN_KEY_DATA_KEYID, hdr, 2, NULL, 0);
5656 }
5657
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005658 if (gtk) {
Hai Shalomc3565922019-10-28 11:58:20 -07005659 hdr[0] = gtkidx & 0x03;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005660 pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
5661 gtk, gtk_len);
5662 }
5663 opos = pos;
5664 pos = ieee80211w_kde_add(sm, pos);
Roshan Pius3a1667e2018-07-03 15:17:14 -07005665 if (pos - opos >= 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN) {
5666 /* skip KDE header and keyid */
5667 opos += 2 + RSN_SELECTOR_LEN + 2;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005668 os_memset(opos, 0, 6); /* clear PN */
5669 }
Hai Shalom899fcc72020-10-19 14:38:18 -07005670 if (ocv_oci_add(sm, &pos, conf->oci_freq_override_eapol_m3) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -08005671 os_free(kde);
5672 return -1;
5673 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005674
5675#ifdef CONFIG_IEEE80211R_AP
5676 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
5677 int res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005678
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005679 if (sm->assoc_resp_ftie &&
5680 kde + kde_len - pos >= 2 + sm->assoc_resp_ftie[1]) {
5681 os_memcpy(pos, sm->assoc_resp_ftie,
5682 2 + sm->assoc_resp_ftie[1]);
5683 res = 2 + sm->assoc_resp_ftie[1];
5684 } else {
Roshan Pius3a1667e2018-07-03 15:17:14 -07005685 int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt);
5686
5687 res = wpa_write_ftie(conf, use_sha384,
5688 conf->r0_key_holder,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005689 conf->r0_key_holder_len,
5690 NULL, NULL, pos,
5691 kde + kde_len - pos,
Hai Shalomfdcde762020-04-02 11:19:20 -07005692 NULL, 0, 0);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005693 }
5694 if (res < 0) {
Hai Shalomfdcde762020-04-02 11:19:20 -07005695 wpa_printf(MSG_ERROR,
5696 "FT: Failed to insert FTIE into EAPOL-Key Key Data");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005697 os_free(kde);
5698 return -1;
5699 }
5700 pos += res;
5701
5702 /* TIE[ReassociationDeadline] (TU) */
5703 *pos++ = WLAN_EID_TIMEOUT_INTERVAL;
5704 *pos++ = 5;
5705 *pos++ = WLAN_TIMEOUT_REASSOC_DEADLINE;
5706 WPA_PUT_LE32(pos, conf->reassociation_deadline);
5707 pos += 4;
5708
5709 /* TIE[KeyLifetime] (seconds) */
5710 *pos++ = WLAN_EID_TIMEOUT_INTERVAL;
5711 *pos++ = 5;
5712 *pos++ = WLAN_TIMEOUT_KEY_LIFETIME;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005713 WPA_PUT_LE32(pos, conf->r0_key_lifetime);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005714 pos += 4;
5715 }
5716#endif /* CONFIG_IEEE80211R_AP */
5717
5718 wpa_send_eapol(sm->wpa_auth, sm,
5719 (secure ? WPA_KEY_INFO_SECURE : 0) |
5720 (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
5721 WPA_KEY_INFO_MIC : 0) |
5722 WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL |
5723 WPA_KEY_INFO_KEY_TYPE,
Hai Shalomc3565922019-10-28 11:58:20 -07005724 _rsc, sm->ANonce, kde, pos - kde, 0, encr);
Sunil Ravia04bd252022-05-02 22:54:18 -07005725 bin_clear_free(kde, kde_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005726 return 0;
5727}
5728
5729
5730int wpa_auth_resend_group_m1(struct wpa_state_machine *sm,
5731 void (*cb)(void *ctx1, void *ctx2),
5732 void *ctx1, void *ctx2)
5733{
5734 u8 rsc[WPA_KEY_RSC_LEN];
Hai Shalom899fcc72020-10-19 14:38:18 -07005735 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005736 struct wpa_group *gsm = sm->group;
5737 const u8 *kde;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005738 u8 *kde_buf = NULL, *pos, hdr[2];
Roshan Pius3a1667e2018-07-03 15:17:14 -07005739 u8 *opos;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005740 size_t kde_len;
5741 u8 *gtk;
5742
5743 /* Send EAPOL(1, 1, 1, !Pair, G, RSC, GNonce, MIC(PTK), GTK[GN]) */
5744 os_memset(rsc, 0, WPA_KEY_RSC_LEN);
5745 /* Use 0 RSC */
5746 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
5747 "sending 1/2 msg of Group Key Handshake (TESTING)");
5748
5749 gtk = gsm->GTK[gsm->GN - 1];
5750 if (sm->wpa == WPA_VERSION_WPA2) {
5751 kde_len = 2 + RSN_SELECTOR_LEN + 2 + gsm->GTK_len +
Hai Shalom74f70d42019-02-11 14:42:39 -08005752 ieee80211w_kde_len(sm) + ocv_oci_len(sm);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005753 kde_buf = os_malloc(kde_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07005754 if (!kde_buf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005755 return -1;
5756
5757 kde = pos = kde_buf;
5758 hdr[0] = gsm->GN & 0x03;
5759 hdr[1] = 0;
5760 pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
5761 gtk, gsm->GTK_len);
5762 opos = pos;
5763 pos = ieee80211w_kde_add(sm, pos);
Roshan Pius3a1667e2018-07-03 15:17:14 -07005764 if (pos - opos >=
5765 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN) {
5766 /* skip KDE header and keyid */
5767 opos += 2 + RSN_SELECTOR_LEN + 2;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005768 os_memset(opos, 0, 6); /* clear PN */
5769 }
Hai Shalom899fcc72020-10-19 14:38:18 -07005770 if (ocv_oci_add(sm, &pos,
5771 conf->oci_freq_override_eapol_g1) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -08005772 os_free(kde_buf);
5773 return -1;
5774 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005775 kde_len = pos - kde;
5776 } else {
5777 kde = gtk;
5778 kde_len = gsm->GTK_len;
5779 }
5780
5781 sm->eapol_status_cb = cb;
5782 sm->eapol_status_cb_ctx1 = ctx1;
5783 sm->eapol_status_cb_ctx2 = ctx2;
5784
5785 wpa_send_eapol(sm->wpa_auth, sm,
5786 WPA_KEY_INFO_SECURE |
5787 (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
5788 WPA_KEY_INFO_MIC : 0) |
5789 WPA_KEY_INFO_ACK |
5790 (!sm->Pair ? WPA_KEY_INFO_INSTALL : 0),
5791 rsc, NULL, kde, kde_len, gsm->GN, 1);
5792
Sunil Ravia04bd252022-05-02 22:54:18 -07005793 bin_clear_free(kde_buf, kde_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005794 return 0;
5795}
5796
Roshan Pius3a1667e2018-07-03 15:17:14 -07005797
5798int wpa_auth_rekey_gtk(struct wpa_authenticator *wpa_auth)
5799{
5800 if (!wpa_auth)
5801 return -1;
5802 eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL);
5803 return eloop_register_timeout(0, 0, wpa_rekey_gtk, wpa_auth, NULL);
5804}
5805
Hai Shalomb755a2a2020-04-23 21:49:02 -07005806
Hai Shaloma20dcd72022-02-04 13:43:00 -08005807int wpa_auth_rekey_ptk(struct wpa_authenticator *wpa_auth,
5808 struct wpa_state_machine *sm)
5809{
5810 if (!wpa_auth || !sm)
5811 return -1;
5812 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "rekeying PTK");
5813 wpa_request_new_ptk(sm);
5814 wpa_sm_step(sm);
5815 return 0;
5816}
5817
5818
Hai Shalomb755a2a2020-04-23 21:49:02 -07005819void wpa_auth_set_ft_rsnxe_used(struct wpa_authenticator *wpa_auth, int val)
5820{
5821 if (wpa_auth)
5822 wpa_auth->conf.ft_rsnxe_used = val;
5823}
5824
Hai Shalom899fcc72020-10-19 14:38:18 -07005825
5826void wpa_auth_set_ocv_override_freq(struct wpa_authenticator *wpa_auth,
5827 enum wpa_auth_ocv_override_frame frame,
5828 unsigned int freq)
5829{
5830 if (!wpa_auth)
5831 return;
5832 switch (frame) {
5833 case WPA_AUTH_OCV_OVERRIDE_EAPOL_M3:
5834 wpa_auth->conf.oci_freq_override_eapol_m3 = freq;
5835 break;
5836 case WPA_AUTH_OCV_OVERRIDE_EAPOL_G1:
5837 wpa_auth->conf.oci_freq_override_eapol_g1 = freq;
5838 break;
5839 case WPA_AUTH_OCV_OVERRIDE_FT_ASSOC:
5840 wpa_auth->conf.oci_freq_override_ft_assoc = freq;
5841 break;
5842 case WPA_AUTH_OCV_OVERRIDE_FILS_ASSOC:
5843 wpa_auth->conf.oci_freq_override_fils_assoc = freq;
5844 break;
5845 }
5846}
5847
Kai Shie75b0652020-11-24 20:31:29 -08005848void wpa_auth_set_skip_send_eapol(struct wpa_authenticator *wpa_auth,
5849 u8 val)
5850{
5851 if (wpa_auth)
5852 wpa_auth->conf.skip_send_eapol = val;
5853}
5854
5855void wpa_auth_set_enable_eapol_large_timeout(struct wpa_authenticator *wpa_auth,
5856 u8 val)
5857{
5858 if (wpa_auth)
5859 wpa_auth->conf.enable_eapol_large_timeout = val;
5860}
5861
5862
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005863#endif /* CONFIG_TESTING_OPTIONS */
Sunil Ravia04bd252022-05-02 22:54:18 -07005864
5865
5866void wpa_auth_sta_radius_psk_resp(struct wpa_state_machine *sm, bool success)
5867{
5868 if (!sm->waiting_radius_psk) {
5869 wpa_printf(MSG_DEBUG,
5870 "Ignore RADIUS PSK response for " MACSTR
5871 " that did not wait one",
5872 MAC2STR(sm->addr));
5873 return;
5874 }
5875
5876 wpa_printf(MSG_DEBUG, "RADIUS PSK response for " MACSTR " (%s)",
5877 MAC2STR(sm->addr), success ? "success" : "fail");
5878 sm->waiting_radius_psk = 0;
5879
5880 if (success) {
5881 /* Try to process the EAPOL-Key msg 2/4 again */
5882 sm->EAPOLKeyReceived = true;
5883 } else {
5884 sm->Disconnect = true;
5885 }
5886
5887 eloop_register_timeout(0, 0, wpa_sm_call_step, sm, NULL);
5888}