blob: 2954af609c1665c6cb70c4be08b6533546beced5 [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
152static inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth,
153 const u8 *addr, int idx, u8 *seq)
154{
Hai Shalomfdcde762020-04-02 11:19:20 -0700155 int res;
156
157 if (!wpa_auth->cb->get_seqnum)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700158 return -1;
Hai Shalomfdcde762020-04-02 11:19:20 -0700159 res = wpa_auth->cb->get_seqnum(wpa_auth->cb_ctx, addr, idx, seq);
160#ifdef CONFIG_TESTING_OPTIONS
161 if (!addr && idx < 4 && wpa_auth->conf.gtk_rsc_override_set) {
162 wpa_printf(MSG_DEBUG,
163 "TESTING: Override GTK RSC %016llx --> %016llx",
164 (long long unsigned) WPA_GET_LE64(seq),
165 (long long unsigned)
166 WPA_GET_LE64(wpa_auth->conf.gtk_rsc_override));
167 os_memcpy(seq, wpa_auth->conf.gtk_rsc_override,
168 WPA_KEY_RSC_LEN);
169 }
170 if (!addr && idx >= 4 && idx <= 5 &&
171 wpa_auth->conf.igtk_rsc_override_set) {
172 wpa_printf(MSG_DEBUG,
173 "TESTING: Override IGTK RSC %016llx --> %016llx",
174 (long long unsigned) WPA_GET_LE64(seq),
175 (long long unsigned)
176 WPA_GET_LE64(wpa_auth->conf.igtk_rsc_override));
177 os_memcpy(seq, wpa_auth->conf.igtk_rsc_override,
178 WPA_KEY_RSC_LEN);
179 }
180#endif /* CONFIG_TESTING_OPTIONS */
181 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700182}
183
184
185static inline int
186wpa_auth_send_eapol(struct wpa_authenticator *wpa_auth, const u8 *addr,
187 const u8 *data, size_t data_len, int encrypt)
188{
Hai Shalomfdcde762020-04-02 11:19:20 -0700189 if (!wpa_auth->cb->send_eapol)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700190 return -1;
Kai Shie75b0652020-11-24 20:31:29 -0800191#ifdef CONFIG_TESTING_OPTIONS
192 if (wpa_auth->conf.skip_send_eapol)
193 return 0;
194#endif
Paul Stewart092955c2017-02-06 09:13:09 -0800195 return wpa_auth->cb->send_eapol(wpa_auth->cb_ctx, addr, data, data_len,
196 encrypt);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700197}
198
199
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800200#ifdef CONFIG_MESH
201static inline int wpa_auth_start_ampe(struct wpa_authenticator *wpa_auth,
202 const u8 *addr)
203{
Hai Shalomfdcde762020-04-02 11:19:20 -0700204 if (!wpa_auth->cb->start_ampe)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800205 return -1;
Paul Stewart092955c2017-02-06 09:13:09 -0800206 return wpa_auth->cb->start_ampe(wpa_auth->cb_ctx, addr);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800207}
208#endif /* CONFIG_MESH */
209
210
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700211int wpa_auth_for_each_sta(struct wpa_authenticator *wpa_auth,
212 int (*cb)(struct wpa_state_machine *sm, void *ctx),
213 void *cb_ctx)
214{
Hai Shalomfdcde762020-04-02 11:19:20 -0700215 if (!wpa_auth->cb->for_each_sta)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700216 return 0;
Paul Stewart092955c2017-02-06 09:13:09 -0800217 return wpa_auth->cb->for_each_sta(wpa_auth->cb_ctx, cb, cb_ctx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700218}
219
220
221int wpa_auth_for_each_auth(struct wpa_authenticator *wpa_auth,
222 int (*cb)(struct wpa_authenticator *a, void *ctx),
223 void *cb_ctx)
224{
Hai Shalomfdcde762020-04-02 11:19:20 -0700225 if (!wpa_auth->cb->for_each_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700226 return 0;
Paul Stewart092955c2017-02-06 09:13:09 -0800227 return wpa_auth->cb->for_each_auth(wpa_auth->cb_ctx, cb, cb_ctx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700228}
229
230
Hai Shalom60840252021-02-19 19:02:11 -0800231void wpa_auth_store_ptksa(struct wpa_authenticator *wpa_auth,
232 const u8 *addr, int cipher,
233 u32 life_time, const struct wpa_ptk *ptk)
234{
235 if (wpa_auth->cb->store_ptksa)
236 wpa_auth->cb->store_ptksa(wpa_auth->cb_ctx, addr, cipher,
237 life_time, ptk);
238}
239
240
241void wpa_auth_remove_ptksa(struct wpa_authenticator *wpa_auth,
242 const u8 *addr, int cipher)
243{
244 if (wpa_auth->cb->clear_ptksa)
245 wpa_auth->cb->clear_ptksa(wpa_auth->cb_ctx, addr, cipher);
246}
247
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700248void wpa_auth_logger(struct wpa_authenticator *wpa_auth, const u8 *addr,
249 logger_level level, const char *txt)
250{
Hai Shalomfdcde762020-04-02 11:19:20 -0700251 if (!wpa_auth->cb->logger)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700252 return;
Paul Stewart092955c2017-02-06 09:13:09 -0800253 wpa_auth->cb->logger(wpa_auth->cb_ctx, addr, level, txt);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700254}
255
256
257void wpa_auth_vlogger(struct wpa_authenticator *wpa_auth, const u8 *addr,
258 logger_level level, const char *fmt, ...)
259{
260 char *format;
261 int maxlen;
262 va_list ap;
263
Hai Shalomfdcde762020-04-02 11:19:20 -0700264 if (!wpa_auth->cb->logger)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700265 return;
266
267 maxlen = os_strlen(fmt) + 100;
268 format = os_malloc(maxlen);
269 if (!format)
270 return;
271
272 va_start(ap, fmt);
273 vsnprintf(format, maxlen, fmt, ap);
274 va_end(ap);
275
276 wpa_auth_logger(wpa_auth, addr, level, format);
277
278 os_free(format);
279}
280
281
282static void wpa_sta_disconnect(struct wpa_authenticator *wpa_auth,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700283 const u8 *addr, u16 reason)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700284{
Hai Shalomfdcde762020-04-02 11:19:20 -0700285 if (!wpa_auth->cb->disconnect)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700286 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700287 wpa_printf(MSG_DEBUG, "wpa_sta_disconnect STA " MACSTR " (reason %u)",
288 MAC2STR(addr), reason);
289 wpa_auth->cb->disconnect(wpa_auth->cb_ctx, addr, reason);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700290}
291
292
Hai Shalom74f70d42019-02-11 14:42:39 -0800293#ifdef CONFIG_OCV
294static int wpa_channel_info(struct wpa_authenticator *wpa_auth,
295 struct wpa_channel_info *ci)
296{
297 if (!wpa_auth->cb->channel_info)
298 return -1;
299 return wpa_auth->cb->channel_info(wpa_auth->cb_ctx, ci);
300}
301#endif /* CONFIG_OCV */
302
303
Hai Shalom021b0b52019-04-10 11:17:58 -0700304static int wpa_auth_update_vlan(struct wpa_authenticator *wpa_auth,
305 const u8 *addr, int vlan_id)
306{
307 if (!wpa_auth->cb->update_vlan)
308 return -1;
309 return wpa_auth->cb->update_vlan(wpa_auth->cb_ctx, addr, vlan_id);
310}
311
312
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700313static void wpa_rekey_gmk(void *eloop_ctx, void *timeout_ctx)
314{
315 struct wpa_authenticator *wpa_auth = eloop_ctx;
316
317 if (random_get_bytes(wpa_auth->group->GMK, WPA_GMK_LEN)) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700318 wpa_printf(MSG_ERROR,
319 "Failed to get random data for WPA initialization.");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700320 } else {
321 wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "GMK rekeyd");
322 wpa_hexdump_key(MSG_DEBUG, "GMK",
323 wpa_auth->group->GMK, WPA_GMK_LEN);
324 }
325
326 if (wpa_auth->conf.wpa_gmk_rekey) {
327 eloop_register_timeout(wpa_auth->conf.wpa_gmk_rekey, 0,
328 wpa_rekey_gmk, wpa_auth, NULL);
329 }
330}
331
332
333static void wpa_rekey_gtk(void *eloop_ctx, void *timeout_ctx)
334{
335 struct wpa_authenticator *wpa_auth = eloop_ctx;
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700336 struct wpa_group *group, *next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700337
338 wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "rekeying GTK");
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700339 group = wpa_auth->group;
340 while (group) {
341 wpa_group_get(wpa_auth, group);
342
Hai Shalome21d4e82020-04-29 16:34:06 -0700343 group->GTKReKey = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700344 do {
Hai Shalome21d4e82020-04-29 16:34:06 -0700345 group->changed = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700346 wpa_group_sm_step(wpa_auth, group);
347 } while (group->changed);
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700348
349 next = group->next;
350 wpa_group_put(wpa_auth, group);
351 group = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700352 }
353
354 if (wpa_auth->conf.wpa_group_rekey) {
355 eloop_register_timeout(wpa_auth->conf.wpa_group_rekey,
356 0, wpa_rekey_gtk, wpa_auth, NULL);
357 }
358}
359
360
361static void wpa_rekey_ptk(void *eloop_ctx, void *timeout_ctx)
362{
363 struct wpa_authenticator *wpa_auth = eloop_ctx;
364 struct wpa_state_machine *sm = timeout_ctx;
365
366 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "rekeying PTK");
367 wpa_request_new_ptk(sm);
368 wpa_sm_step(sm);
369}
370
371
Hai Shalom81f62d82019-07-22 12:10:00 -0700372void wpa_auth_set_ptk_rekey_timer(struct wpa_state_machine *sm)
373{
374 if (sm && sm->wpa_auth->conf.wpa_ptk_rekey) {
375 wpa_printf(MSG_DEBUG, "WPA: Start PTK rekeying timer for "
376 MACSTR " (%d seconds)", MAC2STR(sm->addr),
377 sm->wpa_auth->conf.wpa_ptk_rekey);
378 eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm);
379 eloop_register_timeout(sm->wpa_auth->conf.wpa_ptk_rekey, 0,
380 wpa_rekey_ptk, sm->wpa_auth, sm);
381 }
382}
383
384
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700385static int wpa_auth_pmksa_clear_cb(struct wpa_state_machine *sm, void *ctx)
386{
387 if (sm->pmksa == ctx)
388 sm->pmksa = NULL;
389 return 0;
390}
391
392
393static void wpa_auth_pmksa_free_cb(struct rsn_pmksa_cache_entry *entry,
394 void *ctx)
395{
396 struct wpa_authenticator *wpa_auth = ctx;
397 wpa_auth_for_each_sta(wpa_auth, wpa_auth_pmksa_clear_cb, entry);
398}
399
400
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700401static int wpa_group_init_gmk_and_counter(struct wpa_authenticator *wpa_auth,
402 struct wpa_group *group)
403{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800404 u8 buf[ETH_ALEN + 8 + sizeof(unsigned long)];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700405 u8 rkey[32];
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800406 unsigned long ptr;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700407
408 if (random_get_bytes(group->GMK, WPA_GMK_LEN) < 0)
409 return -1;
410 wpa_hexdump_key(MSG_DEBUG, "GMK", group->GMK, WPA_GMK_LEN);
411
412 /*
413 * Counter = PRF-256(Random number, "Init Counter",
414 * Local MAC Address || Time)
415 */
416 os_memcpy(buf, wpa_auth->addr, ETH_ALEN);
417 wpa_get_ntp_timestamp(buf + ETH_ALEN);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800418 ptr = (unsigned long) group;
419 os_memcpy(buf + ETH_ALEN + 8, &ptr, sizeof(ptr));
Hai Shalom74f70d42019-02-11 14:42:39 -0800420#ifdef TEST_FUZZ
421 os_memset(buf + ETH_ALEN, 0xab, 8);
422 os_memset(buf + ETH_ALEN + 8, 0xcd, sizeof(ptr));
423#endif /* TEST_FUZZ */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700424 if (random_get_bytes(rkey, sizeof(rkey)) < 0)
425 return -1;
426
427 if (sha1_prf(rkey, sizeof(rkey), "Init Counter", buf, sizeof(buf),
428 group->Counter, WPA_NONCE_LEN) < 0)
429 return -1;
430 wpa_hexdump_key(MSG_DEBUG, "Key Counter",
431 group->Counter, WPA_NONCE_LEN);
432
433 return 0;
434}
435
436
437static struct wpa_group * wpa_group_init(struct wpa_authenticator *wpa_auth,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800438 int vlan_id, int delay_init)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700439{
440 struct wpa_group *group;
441
442 group = os_zalloc(sizeof(struct wpa_group));
Hai Shalomfdcde762020-04-02 11:19:20 -0700443 if (!group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700444 return NULL;
445
Hai Shalome21d4e82020-04-29 16:34:06 -0700446 group->GTKAuthenticator = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700447 group->vlan_id = vlan_id;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -0700448 group->GTK_len = wpa_cipher_key_len(wpa_auth->conf.wpa_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700449
450 if (random_pool_ready() != 1) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700451 wpa_printf(MSG_INFO,
452 "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 -0700453 }
454
455 /*
456 * Set initial GMK/Counter value here. The actual values that will be
457 * used in negotiations will be set once the first station tries to
458 * connect. This allows more time for collecting additional randomness
459 * on embedded devices.
460 */
461 if (wpa_group_init_gmk_and_counter(wpa_auth, group) < 0) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700462 wpa_printf(MSG_ERROR,
463 "Failed to get random data for WPA initialization.");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700464 os_free(group);
465 return NULL;
466 }
467
Hai Shalome21d4e82020-04-29 16:34:06 -0700468 group->GInit = true;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800469 if (delay_init) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700470 wpa_printf(MSG_DEBUG,
471 "WPA: Delay group state machine start until Beacon frames have been configured");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800472 /* Initialization is completed in wpa_init_keys(). */
473 } else {
474 wpa_group_sm_step(wpa_auth, group);
Hai Shalome21d4e82020-04-29 16:34:06 -0700475 group->GInit = false;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800476 wpa_group_sm_step(wpa_auth, group);
477 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700478
479 return group;
480}
481
482
483/**
484 * wpa_init - Initialize WPA authenticator
485 * @addr: Authenticator address
486 * @conf: Configuration for WPA authenticator
487 * @cb: Callback functions for WPA authenticator
488 * Returns: Pointer to WPA authenticator data or %NULL on failure
489 */
490struct wpa_authenticator * wpa_init(const u8 *addr,
491 struct wpa_auth_config *conf,
Paul Stewart092955c2017-02-06 09:13:09 -0800492 const struct wpa_auth_callbacks *cb,
493 void *cb_ctx)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700494{
495 struct wpa_authenticator *wpa_auth;
496
497 wpa_auth = os_zalloc(sizeof(struct wpa_authenticator));
Hai Shalomfdcde762020-04-02 11:19:20 -0700498 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700499 return NULL;
500 os_memcpy(wpa_auth->addr, addr, ETH_ALEN);
501 os_memcpy(&wpa_auth->conf, conf, sizeof(*conf));
Paul Stewart092955c2017-02-06 09:13:09 -0800502 wpa_auth->cb = cb;
503 wpa_auth->cb_ctx = cb_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700504
505 if (wpa_auth_gen_wpa_ie(wpa_auth)) {
506 wpa_printf(MSG_ERROR, "Could not generate WPA IE.");
507 os_free(wpa_auth);
508 return NULL;
509 }
510
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800511 wpa_auth->group = wpa_group_init(wpa_auth, 0, 1);
Hai Shalomfdcde762020-04-02 11:19:20 -0700512 if (!wpa_auth->group) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700513 os_free(wpa_auth->wpa_ie);
514 os_free(wpa_auth);
515 return NULL;
516 }
517
518 wpa_auth->pmksa = pmksa_cache_auth_init(wpa_auth_pmksa_free_cb,
519 wpa_auth);
Hai Shalomfdcde762020-04-02 11:19:20 -0700520 if (!wpa_auth->pmksa) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700521 wpa_printf(MSG_ERROR, "PMKSA cache initialization failed.");
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800522 os_free(wpa_auth->group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700523 os_free(wpa_auth->wpa_ie);
524 os_free(wpa_auth);
525 return NULL;
526 }
527
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800528#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700529 wpa_auth->ft_pmk_cache = wpa_ft_pmk_cache_init();
Hai Shalomfdcde762020-04-02 11:19:20 -0700530 if (!wpa_auth->ft_pmk_cache) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700531 wpa_printf(MSG_ERROR, "FT PMK cache initialization failed.");
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800532 os_free(wpa_auth->group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700533 os_free(wpa_auth->wpa_ie);
534 pmksa_cache_auth_deinit(wpa_auth->pmksa);
535 os_free(wpa_auth);
536 return NULL;
537 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800538#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700539
540 if (wpa_auth->conf.wpa_gmk_rekey) {
541 eloop_register_timeout(wpa_auth->conf.wpa_gmk_rekey, 0,
542 wpa_rekey_gmk, wpa_auth, NULL);
543 }
544
545 if (wpa_auth->conf.wpa_group_rekey) {
546 eloop_register_timeout(wpa_auth->conf.wpa_group_rekey, 0,
547 wpa_rekey_gtk, wpa_auth, NULL);
548 }
549
Dmitry Shmidtcf32e602014-01-28 10:57:39 -0800550#ifdef CONFIG_P2P
551 if (WPA_GET_BE32(conf->ip_addr_start)) {
552 int count = WPA_GET_BE32(conf->ip_addr_end) -
553 WPA_GET_BE32(conf->ip_addr_start) + 1;
554 if (count > 1000)
555 count = 1000;
556 if (count > 0)
557 wpa_auth->ip_pool = bitfield_alloc(count);
558 }
559#endif /* CONFIG_P2P */
560
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700561 return wpa_auth;
562}
563
564
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800565int wpa_init_keys(struct wpa_authenticator *wpa_auth)
566{
567 struct wpa_group *group = wpa_auth->group;
568
Hai Shalomfdcde762020-04-02 11:19:20 -0700569 wpa_printf(MSG_DEBUG,
570 "WPA: Start group state machine to set initial keys");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800571 wpa_group_sm_step(wpa_auth, group);
Hai Shalome21d4e82020-04-29 16:34:06 -0700572 group->GInit = false;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800573 wpa_group_sm_step(wpa_auth, group);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800574 if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
575 return -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800576 return 0;
577}
578
579
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700580/**
581 * wpa_deinit - Deinitialize WPA authenticator
582 * @wpa_auth: Pointer to WPA authenticator data from wpa_init()
583 */
584void wpa_deinit(struct wpa_authenticator *wpa_auth)
585{
586 struct wpa_group *group, *prev;
587
588 eloop_cancel_timeout(wpa_rekey_gmk, wpa_auth, NULL);
589 eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL);
590
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700591 pmksa_cache_auth_deinit(wpa_auth->pmksa);
592
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800593#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700594 wpa_ft_pmk_cache_deinit(wpa_auth->ft_pmk_cache);
595 wpa_auth->ft_pmk_cache = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700596 wpa_ft_deinit(wpa_auth);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800597#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700598
Dmitry Shmidtcf32e602014-01-28 10:57:39 -0800599#ifdef CONFIG_P2P
600 bitfield_free(wpa_auth->ip_pool);
601#endif /* CONFIG_P2P */
602
603
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700604 os_free(wpa_auth->wpa_ie);
605
606 group = wpa_auth->group;
607 while (group) {
608 prev = group;
609 group = group->next;
Sunil Ravia04bd252022-05-02 22:54:18 -0700610 bin_clear_free(prev, sizeof(*prev));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700611 }
612
613 os_free(wpa_auth);
614}
615
616
617/**
618 * wpa_reconfig - Update WPA authenticator configuration
619 * @wpa_auth: Pointer to WPA authenticator data from wpa_init()
620 * @conf: Configuration for WPA authenticator
621 */
622int wpa_reconfig(struct wpa_authenticator *wpa_auth,
623 struct wpa_auth_config *conf)
624{
625 struct wpa_group *group;
Hai Shalomfdcde762020-04-02 11:19:20 -0700626
627 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700628 return 0;
629
630 os_memcpy(&wpa_auth->conf, conf, sizeof(*conf));
631 if (wpa_auth_gen_wpa_ie(wpa_auth)) {
632 wpa_printf(MSG_ERROR, "Could not generate WPA IE.");
633 return -1;
634 }
635
636 /*
637 * Reinitialize GTK to make sure it is suitable for the new
638 * configuration.
639 */
640 group = wpa_auth->group;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -0700641 group->GTK_len = wpa_cipher_key_len(wpa_auth->conf.wpa_group);
Hai Shalome21d4e82020-04-29 16:34:06 -0700642 group->GInit = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700643 wpa_group_sm_step(wpa_auth, group);
Hai Shalome21d4e82020-04-29 16:34:06 -0700644 group->GInit = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700645 wpa_group_sm_step(wpa_auth, group);
646
647 return 0;
648}
649
650
651struct wpa_state_machine *
Dmitry Shmidt391c59f2013-09-03 12:16:28 -0700652wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr,
653 const u8 *p2p_dev_addr)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700654{
655 struct wpa_state_machine *sm;
656
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800657 if (wpa_auth->group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
658 return NULL;
659
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700660 sm = os_zalloc(sizeof(struct wpa_state_machine));
Hai Shalomfdcde762020-04-02 11:19:20 -0700661 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700662 return NULL;
663 os_memcpy(sm->addr, addr, ETH_ALEN);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -0700664 if (p2p_dev_addr)
665 os_memcpy(sm->p2p_dev_addr, p2p_dev_addr, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700666
667 sm->wpa_auth = wpa_auth;
668 sm->group = wpa_auth->group;
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700669 wpa_group_get(sm->wpa_auth, sm->group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700670
671 return sm;
672}
673
674
675int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth,
676 struct wpa_state_machine *sm)
677{
Hai Shalomfdcde762020-04-02 11:19:20 -0700678 if (!wpa_auth || !wpa_auth->conf.wpa || !sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700679 return -1;
680
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800681#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700682 if (sm->ft_completed) {
683 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -0700684 "FT authentication already completed - do not start 4-way handshake");
Dmitry Shmidt71757432014-06-02 13:50:35 -0700685 /* Go to PTKINITDONE state to allow GTK rekeying */
686 sm->wpa_ptk_state = WPA_PTK_PTKINITDONE;
Hai Shalome21d4e82020-04-29 16:34:06 -0700687 sm->Pair = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700688 return 0;
689 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800690#endif /* CONFIG_IEEE80211R_AP */
691
692#ifdef CONFIG_FILS
693 if (sm->fils_completed) {
694 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
695 "FILS authentication already completed - do not start 4-way handshake");
696 /* Go to PTKINITDONE state to allow GTK rekeying */
697 sm->wpa_ptk_state = WPA_PTK_PTKINITDONE;
Hai Shalome21d4e82020-04-29 16:34:06 -0700698 sm->Pair = true;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800699 return 0;
700 }
701#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700702
703 if (sm->started) {
704 os_memset(&sm->key_replay, 0, sizeof(sm->key_replay));
Hai Shalome21d4e82020-04-29 16:34:06 -0700705 sm->ReAuthenticationRequest = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700706 return wpa_sm_step(sm);
707 }
708
709 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
710 "start authentication");
711 sm->started = 1;
712
Hai Shalome21d4e82020-04-29 16:34:06 -0700713 sm->Init = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700714 if (wpa_sm_step(sm) == 1)
715 return 1; /* should not really happen */
Hai Shalome21d4e82020-04-29 16:34:06 -0700716 sm->Init = false;
717 sm->AuthenticationRequest = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700718 return wpa_sm_step(sm);
719}
720
721
722void wpa_auth_sta_no_wpa(struct wpa_state_machine *sm)
723{
724 /* WPA/RSN was not used - clear WPA state. This is needed if the STA
725 * reassociates back to the same AP while the previous entry for the
726 * STA has not yet been removed. */
Hai Shalomfdcde762020-04-02 11:19:20 -0700727 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700728 return;
729
730 sm->wpa_key_mgmt = 0;
731}
732
733
734static void wpa_free_sta_sm(struct wpa_state_machine *sm)
735{
Dmitry Shmidtcf32e602014-01-28 10:57:39 -0800736#ifdef CONFIG_P2P
737 if (WPA_GET_BE32(sm->ip_addr)) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700738 wpa_printf(MSG_DEBUG,
739 "P2P: Free assigned IP address %u.%u.%u.%u from "
Sunil8cd6f4d2022-06-28 18:40:46 +0000740 MACSTR " (bit %u)",
Dmitry Shmidtcf32e602014-01-28 10:57:39 -0800741 sm->ip_addr[0], sm->ip_addr[1],
742 sm->ip_addr[2], sm->ip_addr[3],
Sunil8cd6f4d2022-06-28 18:40:46 +0000743 MAC2STR(sm->addr), sm->ip_addr_bit);
744 bitfield_clear(sm->wpa_auth->ip_pool, sm->ip_addr_bit);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -0800745 }
746#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700747 if (sm->GUpdateStationKeys) {
748 sm->group->GKeyDoneStations--;
Hai Shalome21d4e82020-04-29 16:34:06 -0700749 sm->GUpdateStationKeys = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700750 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800751#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700752 os_free(sm->assoc_resp_ftie);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700753 wpabuf_free(sm->ft_pending_req_ies);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800754#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700755 os_free(sm->last_rx_eapol_key);
756 os_free(sm->wpa_ie);
Hai Shalomc3565922019-10-28 11:58:20 -0700757 os_free(sm->rsnxe);
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700758 wpa_group_put(sm->wpa_auth, sm->group);
Hai Shalom021b0b52019-04-10 11:17:58 -0700759#ifdef CONFIG_DPP2
760 wpabuf_clear_free(sm->dpp_z);
761#endif /* CONFIG_DPP2 */
Hai Shalom1dc4d202019-04-29 16:22:27 -0700762 bin_clear_free(sm, sizeof(*sm));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700763}
764
765
766void wpa_auth_sta_deinit(struct wpa_state_machine *sm)
767{
Hai Shalomfdcde762020-04-02 11:19:20 -0700768 struct wpa_authenticator *wpa_auth;
769
770 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700771 return;
772
Hai Shalomfdcde762020-04-02 11:19:20 -0700773 wpa_auth = sm->wpa_auth;
774 if (wpa_auth->conf.wpa_strict_rekey && sm->has_GTK) {
775 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
776 "strict rekeying - force GTK rekey since STA is leaving");
Roshan Pius3a1667e2018-07-03 15:17:14 -0700777 if (eloop_deplete_timeout(0, 500000, wpa_rekey_gtk,
Hai Shalomfdcde762020-04-02 11:19:20 -0700778 wpa_auth, NULL) == -1)
779 eloop_register_timeout(0, 500000, wpa_rekey_gtk,
780 wpa_auth, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700781 }
782
Hai Shalomfdcde762020-04-02 11:19:20 -0700783 eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700784 sm->pending_1_of_4_timeout = 0;
785 eloop_cancel_timeout(wpa_sm_call_step, sm, NULL);
Hai Shalomfdcde762020-04-02 11:19:20 -0700786 eloop_cancel_timeout(wpa_rekey_ptk, wpa_auth, sm);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700787#ifdef CONFIG_IEEE80211R_AP
788 wpa_ft_sta_deinit(sm);
789#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700790 if (sm->in_step_loop) {
791 /* Must not free state machine while wpa_sm_step() is running.
792 * Freeing will be completed in the end of wpa_sm_step(). */
Hai Shalomfdcde762020-04-02 11:19:20 -0700793 wpa_printf(MSG_DEBUG,
794 "WPA: Registering pending STA state machine deinit for "
795 MACSTR, MAC2STR(sm->addr));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700796 sm->pending_deinit = 1;
797 } else
798 wpa_free_sta_sm(sm);
799}
800
801
802static void wpa_request_new_ptk(struct wpa_state_machine *sm)
803{
Hai Shalomfdcde762020-04-02 11:19:20 -0700804 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700805 return;
806
Hai Shalomfdcde762020-04-02 11:19:20 -0700807 if (!sm->use_ext_key_id && sm->wpa_auth->conf.wpa_deny_ptk0_rekey) {
808 wpa_printf(MSG_INFO,
809 "WPA: PTK0 rekey not allowed, disconnect " MACSTR,
810 MAC2STR(sm->addr));
Hai Shalome21d4e82020-04-29 16:34:06 -0700811 sm->Disconnect = true;
Hai Shalomfdcde762020-04-02 11:19:20 -0700812 /* Try to encourage the STA to reconnect */
813 sm->disconnect_reason =
814 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA;
815 } else {
816 if (sm->use_ext_key_id)
817 sm->keyidx_active ^= 1; /* flip Key ID */
Hai Shalome21d4e82020-04-29 16:34:06 -0700818 sm->PTKRequest = true;
Hai Shalomfdcde762020-04-02 11:19:20 -0700819 sm->PTK_valid = 0;
820 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700821}
822
823
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800824static int wpa_replay_counter_valid(struct wpa_key_replay_counter *ctr,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700825 const u8 *replay_counter)
826{
827 int i;
828 for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800829 if (!ctr[i].valid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700830 break;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800831 if (os_memcmp(replay_counter, ctr[i].counter,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700832 WPA_REPLAY_COUNTER_LEN) == 0)
833 return 1;
834 }
835 return 0;
836}
837
838
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800839static void wpa_replay_counter_mark_invalid(struct wpa_key_replay_counter *ctr,
840 const u8 *replay_counter)
841{
842 int i;
843 for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) {
844 if (ctr[i].valid &&
Hai Shalomfdcde762020-04-02 11:19:20 -0700845 (!replay_counter ||
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800846 os_memcmp(replay_counter, ctr[i].counter,
847 WPA_REPLAY_COUNTER_LEN) == 0))
Hai Shalome21d4e82020-04-29 16:34:06 -0700848 ctr[i].valid = false;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800849 }
850}
851
852
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800853#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700854static int ft_check_msg_2_of_4(struct wpa_authenticator *wpa_auth,
855 struct wpa_state_machine *sm,
856 struct wpa_eapol_ie_parse *kde)
857{
858 struct wpa_ie_data ie;
859 struct rsn_mdie *mdie;
860
861 if (wpa_parse_wpa_ie_rsn(kde->rsn_ie, kde->rsn_ie_len, &ie) < 0 ||
Hai Shalomfdcde762020-04-02 11:19:20 -0700862 ie.num_pmkid != 1 || !ie.pmkid) {
863 wpa_printf(MSG_DEBUG,
864 "FT: No PMKR1Name in FT 4-way handshake message 2/4");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700865 return -1;
866 }
867
868 os_memcpy(sm->sup_pmk_r1_name, ie.pmkid, PMKID_LEN);
869 wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from Supplicant",
870 sm->sup_pmk_r1_name, PMKID_LEN);
871
872 if (!kde->mdie || !kde->ftie) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700873 wpa_printf(MSG_DEBUG,
874 "FT: No %s in FT 4-way handshake message 2/4",
875 kde->mdie ? "FTIE" : "MDIE");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700876 return -1;
877 }
878
879 mdie = (struct rsn_mdie *) (kde->mdie + 2);
880 if (kde->mdie[1] < sizeof(struct rsn_mdie) ||
881 os_memcmp(wpa_auth->conf.mobility_domain, mdie->mobility_domain,
882 MOBILITY_DOMAIN_ID_LEN) != 0) {
883 wpa_printf(MSG_DEBUG, "FT: MDIE mismatch");
884 return -1;
885 }
886
887 if (sm->assoc_resp_ftie &&
888 (kde->ftie[1] != sm->assoc_resp_ftie[1] ||
889 os_memcmp(kde->ftie, sm->assoc_resp_ftie,
890 2 + sm->assoc_resp_ftie[1]) != 0)) {
891 wpa_printf(MSG_DEBUG, "FT: FTIE mismatch");
892 wpa_hexdump(MSG_DEBUG, "FT: FTIE in EAPOL-Key msg 2/4",
893 kde->ftie, kde->ftie_len);
894 wpa_hexdump(MSG_DEBUG, "FT: FTIE in (Re)AssocResp",
895 sm->assoc_resp_ftie, 2 + sm->assoc_resp_ftie[1]);
896 return -1;
897 }
898
899 return 0;
900}
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800901#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700902
903
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800904static int wpa_receive_error_report(struct wpa_authenticator *wpa_auth,
905 struct wpa_state_machine *sm, int group)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800906{
907 /* Supplicant reported a Michael MIC error */
908 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -0700909 "received EAPOL-Key Error Request (STA detected Michael MIC failure (group=%d))",
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800910 group);
911
912 if (group && wpa_auth->conf.wpa_group != WPA_CIPHER_TKIP) {
913 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -0700914 "ignore Michael MIC failure report since group cipher is not TKIP");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800915 } else if (!group && sm->pairwise != WPA_CIPHER_TKIP) {
916 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -0700917 "ignore Michael MIC failure report since pairwise cipher is not TKIP");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800918 } else {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800919 if (wpa_auth_mic_failure_report(wpa_auth, sm->addr) > 0)
920 return 1; /* STA entry was removed */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800921 sm->dot11RSNAStatsTKIPRemoteMICFailures++;
922 wpa_auth->dot11RSNAStatsTKIPRemoteMICFailures++;
923 }
924
925 /*
926 * Error report is not a request for a new key handshake, but since
927 * Authenticator may do it, let's change the keys now anyway.
928 */
929 wpa_request_new_ptk(sm);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800930 return 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800931}
932
933
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800934static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data,
935 size_t data_len)
936{
937 struct wpa_ptk PTK;
938 int ok = 0;
939 const u8 *pmk = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700940 size_t pmk_len;
Hai Shalom021b0b52019-04-10 11:17:58 -0700941 int vlan_id = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800942
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800943 os_memset(&PTK, 0, sizeof(PTK));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800944 for (;;) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700945 if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
946 !wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800947 pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr,
Hai Shalom021b0b52019-04-10 11:17:58 -0700948 sm->p2p_dev_addr, pmk, &pmk_len,
949 &vlan_id);
Hai Shalomfdcde762020-04-02 11:19:20 -0700950 if (!pmk)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800951 break;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700952#ifdef CONFIG_IEEE80211R_AP
953 if (wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) {
954 os_memcpy(sm->xxkey, pmk, pmk_len);
955 sm->xxkey_len = pmk_len;
956 }
957#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800958 } else {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800959 pmk = sm->PMK;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800960 pmk_len = sm->pmk_len;
961 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800962
Hai Shalomfdcde762020-04-02 11:19:20 -0700963 if (wpa_derive_ptk(sm, sm->alt_SNonce, pmk, pmk_len, &PTK, 0) <
964 0)
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800965 break;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800966
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700967 if (wpa_verify_key_mic(sm->wpa_key_mgmt, pmk_len, &PTK,
968 data, data_len) == 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -0700969 if (sm->PMK != pmk) {
970 os_memcpy(sm->PMK, pmk, pmk_len);
971 sm->pmk_len = pmk_len;
972 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800973 ok = 1;
974 break;
975 }
976
Roshan Pius3a1667e2018-07-03 15:17:14 -0700977 if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
978 wpa_key_mgmt_sae(sm->wpa_key_mgmt))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800979 break;
980 }
981
982 if (!ok) {
983 wpa_printf(MSG_DEBUG,
984 "WPA: Earlier SNonce did not result in matching MIC");
985 return -1;
986 }
987
988 wpa_printf(MSG_DEBUG,
989 "WPA: Earlier SNonce resulted in matching MIC");
990 sm->alt_snonce_valid = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -0700991
992 if (vlan_id && wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
993 wpa_auth_update_vlan(sm->wpa_auth, sm->addr, vlan_id) < 0)
994 return -1;
995
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800996 os_memcpy(sm->SNonce, sm->alt_SNonce, WPA_NONCE_LEN);
997 os_memcpy(&sm->PTK, &PTK, sizeof(PTK));
Hai Shalom81f62d82019-07-22 12:10:00 -0700998 forced_memzero(&PTK, sizeof(PTK));
Hai Shalome21d4e82020-04-29 16:34:06 -0700999 sm->PTK_valid = true;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001000
1001 return 0;
1002}
1003
1004
Hai Shaloma20dcd72022-02-04 13:43:00 -08001005static bool wpa_auth_gtk_rekey_in_process(struct wpa_authenticator *wpa_auth)
1006{
1007 struct wpa_group *group;
1008
1009 for (group = wpa_auth->group; group; group = group->next) {
1010 if (group->GKeyDoneStations)
1011 return true;
1012 }
1013 return false;
1014}
1015
1016
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001017void wpa_receive(struct wpa_authenticator *wpa_auth,
1018 struct wpa_state_machine *sm,
1019 u8 *data, size_t data_len)
1020{
1021 struct ieee802_1x_hdr *hdr;
1022 struct wpa_eapol_key *key;
1023 u16 key_info, key_data_length;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001024 enum { PAIRWISE_2, PAIRWISE_4, GROUP_2, REQUEST } msg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001025 char *msgtxt;
1026 struct wpa_eapol_ie_parse kde;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001027 const u8 *key_data;
1028 size_t keyhdrlen, mic_len;
1029 u8 *mic;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001030
Hai Shalomfdcde762020-04-02 11:19:20 -07001031 if (!wpa_auth || !wpa_auth->conf.wpa || !sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001032 return;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001033 wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL data", data, data_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001034
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001035 mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001036 keyhdrlen = sizeof(*key) + mic_len + 2;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001037
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001038 if (data_len < sizeof(*hdr) + keyhdrlen) {
1039 wpa_printf(MSG_DEBUG, "WPA: Ignore too short EAPOL-Key frame");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001040 return;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001041 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001042
1043 hdr = (struct ieee802_1x_hdr *) data;
1044 key = (struct wpa_eapol_key *) (hdr + 1);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001045 mic = (u8 *) (key + 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001046 key_info = WPA_GET_BE16(key->key_info);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001047 key_data = mic + mic_len + 2;
1048 key_data_length = WPA_GET_BE16(mic + mic_len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001049 wpa_printf(MSG_DEBUG, "WPA: Received EAPOL-Key from " MACSTR
Hai Shalomfdcde762020-04-02 11:19:20 -07001050 " key_info=0x%x type=%u mic_len=%zu key_data_length=%u",
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001051 MAC2STR(sm->addr), key_info, key->type,
Hai Shalomfdcde762020-04-02 11:19:20 -07001052 mic_len, key_data_length);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001053 wpa_hexdump(MSG_MSGDUMP,
1054 "WPA: EAPOL-Key header (ending before Key MIC)",
1055 key, sizeof(*key));
1056 wpa_hexdump(MSG_MSGDUMP, "WPA: EAPOL-Key Key MIC",
1057 mic, mic_len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001058 if (key_data_length > data_len - sizeof(*hdr) - keyhdrlen) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001059 wpa_printf(MSG_INFO,
1060 "WPA: Invalid EAPOL-Key frame - key_data overflow (%d > %zu)",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001061 key_data_length,
Hai Shalomfdcde762020-04-02 11:19:20 -07001062 data_len - sizeof(*hdr) - keyhdrlen);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001063 return;
1064 }
1065
1066 if (sm->wpa == WPA_VERSION_WPA2) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001067 if (key->type == EAPOL_KEY_TYPE_WPA) {
1068 /*
1069 * Some deployed station implementations seem to send
1070 * msg 4/4 with incorrect type value in WPA2 mode.
1071 */
Hai Shalomfdcde762020-04-02 11:19:20 -07001072 wpa_printf(MSG_DEBUG,
1073 "Workaround: Allow EAPOL-Key with unexpected WPA type in RSN mode");
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001074 } else if (key->type != EAPOL_KEY_TYPE_RSN) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001075 wpa_printf(MSG_DEBUG,
1076 "Ignore EAPOL-Key with unexpected type %d in RSN mode",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001077 key->type);
1078 return;
1079 }
1080 } else {
1081 if (key->type != EAPOL_KEY_TYPE_WPA) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001082 wpa_printf(MSG_DEBUG,
1083 "Ignore EAPOL-Key with unexpected type %d in WPA mode",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001084 key->type);
1085 return;
1086 }
1087 }
1088
1089 wpa_hexdump(MSG_DEBUG, "WPA: Received Key Nonce", key->key_nonce,
1090 WPA_NONCE_LEN);
1091 wpa_hexdump(MSG_DEBUG, "WPA: Received Replay Counter",
1092 key->replay_counter, WPA_REPLAY_COUNTER_LEN);
1093
1094 /* FIX: verify that the EAPOL-Key frame was encrypted if pairwise keys
1095 * are set */
1096
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001097 if (key_info & WPA_KEY_INFO_SMK_MESSAGE) {
1098 wpa_printf(MSG_DEBUG, "WPA: Ignore SMK message");
1099 return;
1100 }
1101
1102 if (key_info & WPA_KEY_INFO_REQUEST) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001103 msg = REQUEST;
1104 msgtxt = "Request";
1105 } else if (!(key_info & WPA_KEY_INFO_KEY_TYPE)) {
1106 msg = GROUP_2;
1107 msgtxt = "2/2 Group";
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001108 } else if (key_data_length == 0 ||
1109 (mic_len == 0 && (key_info & WPA_KEY_INFO_ENCR_KEY_DATA) &&
1110 key_data_length == AES_BLOCK_SIZE)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001111 msg = PAIRWISE_4;
1112 msgtxt = "4/4 Pairwise";
1113 } else {
1114 msg = PAIRWISE_2;
1115 msgtxt = "2/4 Pairwise";
1116 }
1117
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001118 if (msg == REQUEST || msg == PAIRWISE_2 || msg == PAIRWISE_4 ||
1119 msg == GROUP_2) {
1120 u16 ver = key_info & WPA_KEY_INFO_TYPE_MASK;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001121 if (sm->pairwise == WPA_CIPHER_CCMP ||
1122 sm->pairwise == WPA_CIPHER_GCMP) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001123 if (wpa_use_cmac(sm->wpa_key_mgmt) &&
1124 !wpa_use_akm_defined(sm->wpa_key_mgmt) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001125 ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) {
1126 wpa_auth_logger(wpa_auth, sm->addr,
1127 LOGGER_WARNING,
Hai Shalomfdcde762020-04-02 11:19:20 -07001128 "advertised support for AES-128-CMAC, but did not use it");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001129 return;
1130 }
1131
Roshan Pius3a1667e2018-07-03 15:17:14 -07001132 if (!wpa_use_cmac(sm->wpa_key_mgmt) &&
1133 !wpa_use_akm_defined(sm->wpa_key_mgmt) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001134 ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
1135 wpa_auth_logger(wpa_auth, sm->addr,
1136 LOGGER_WARNING,
Hai Shalomfdcde762020-04-02 11:19:20 -07001137 "did not use HMAC-SHA1-AES with CCMP/GCMP");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001138 return;
1139 }
1140 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001141
Roshan Pius3a1667e2018-07-03 15:17:14 -07001142 if (wpa_use_akm_defined(sm->wpa_key_mgmt) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001143 ver != WPA_KEY_INFO_TYPE_AKM_DEFINED) {
1144 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING,
1145 "did not use EAPOL-Key descriptor version 0 as required for AKM-defined cases");
1146 return;
1147 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001148 }
1149
1150 if (key_info & WPA_KEY_INFO_REQUEST) {
1151 if (sm->req_replay_counter_used &&
1152 os_memcmp(key->replay_counter, sm->req_replay_counter,
1153 WPA_REPLAY_COUNTER_LEN) <= 0) {
1154 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING,
Hai Shalomfdcde762020-04-02 11:19:20 -07001155 "received EAPOL-Key request with replayed counter");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001156 return;
1157 }
1158 }
1159
1160 if (!(key_info & WPA_KEY_INFO_REQUEST) &&
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001161 !wpa_replay_counter_valid(sm->key_replay, key->replay_counter)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001162 int i;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001163
1164 if (msg == PAIRWISE_2 &&
1165 wpa_replay_counter_valid(sm->prev_key_replay,
1166 key->replay_counter) &&
1167 sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING &&
1168 os_memcmp(sm->SNonce, key->key_nonce, WPA_NONCE_LEN) != 0)
1169 {
1170 /*
1171 * Some supplicant implementations (e.g., Windows XP
1172 * WZC) update SNonce for each EAPOL-Key 2/4. This
1173 * breaks the workaround on accepting any of the
1174 * pending requests, so allow the SNonce to be updated
1175 * even if we have already sent out EAPOL-Key 3/4.
1176 */
1177 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07001178 "Process SNonce update from STA based on retransmitted EAPOL-Key 1/4");
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001179 sm->update_snonce = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001180 os_memcpy(sm->alt_SNonce, sm->SNonce, WPA_NONCE_LEN);
Hai Shalome21d4e82020-04-29 16:34:06 -07001181 sm->alt_snonce_valid = true;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001182 os_memcpy(sm->alt_replay_counter,
1183 sm->key_replay[0].counter,
1184 WPA_REPLAY_COUNTER_LEN);
1185 goto continue_processing;
1186 }
1187
1188 if (msg == PAIRWISE_4 && sm->alt_snonce_valid &&
1189 sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING &&
1190 os_memcmp(key->replay_counter, sm->alt_replay_counter,
1191 WPA_REPLAY_COUNTER_LEN) == 0) {
1192 /*
1193 * Supplicant may still be using the old SNonce since
1194 * there was two EAPOL-Key 2/4 messages and they had
1195 * different SNonce values.
1196 */
1197 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
1198 "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 -08001199 goto continue_processing;
1200 }
1201
1202 if (msg == PAIRWISE_2 &&
1203 wpa_replay_counter_valid(sm->prev_key_replay,
1204 key->replay_counter) &&
1205 sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING) {
1206 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07001207 "ignore retransmitted EAPOL-Key %s - SNonce did not change",
1208 msgtxt);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001209 } else {
1210 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07001211 "received EAPOL-Key %s with unexpected replay counter",
1212 msgtxt);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001213 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001214 for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) {
1215 if (!sm->key_replay[i].valid)
1216 break;
1217 wpa_hexdump(MSG_DEBUG, "pending replay counter",
1218 sm->key_replay[i].counter,
1219 WPA_REPLAY_COUNTER_LEN);
1220 }
1221 wpa_hexdump(MSG_DEBUG, "received replay counter",
1222 key->replay_counter, WPA_REPLAY_COUNTER_LEN);
1223 return;
1224 }
1225
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001226continue_processing:
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001227#ifdef CONFIG_FILS
1228 if (sm->wpa == WPA_VERSION_WPA2 && mic_len == 0 &&
1229 !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
1230 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
1231 "WPA: Encr Key Data bit not set even though AEAD cipher is supposed to be used - drop frame");
1232 return;
1233 }
1234#endif /* CONFIG_FILS */
1235
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001236 switch (msg) {
1237 case PAIRWISE_2:
1238 if (sm->wpa_ptk_state != WPA_PTK_PTKSTART &&
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001239 sm->wpa_ptk_state != WPA_PTK_PTKCALCNEGOTIATING &&
1240 (!sm->update_snonce ||
1241 sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001242 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001243 "received EAPOL-Key msg 2/4 in invalid state (%d) - dropped",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001244 sm->wpa_ptk_state);
1245 return;
1246 }
1247 random_add_randomness(key->key_nonce, WPA_NONCE_LEN);
1248 if (sm->group->reject_4way_hs_for_entropy) {
1249 /*
1250 * The system did not have enough entropy to generate
1251 * strong random numbers. Reject the first 4-way
1252 * handshake(s) and collect some entropy based on the
1253 * information from it. Once enough entropy is
1254 * available, the next atempt will trigger GMK/Key
1255 * Counter update and the station will be allowed to
1256 * continue.
1257 */
Hai Shalomfdcde762020-04-02 11:19:20 -07001258 wpa_printf(MSG_DEBUG,
1259 "WPA: Reject 4-way handshake to collect more entropy for random number generation");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001260 random_mark_pool_ready();
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001261 wpa_sta_disconnect(wpa_auth, sm->addr,
1262 WLAN_REASON_PREV_AUTH_NOT_VALID);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001263 return;
1264 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001265 break;
1266 case PAIRWISE_4:
1267 if (sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING ||
1268 !sm->PTK_valid) {
1269 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001270 "received EAPOL-Key msg 4/4 in invalid state (%d) - dropped",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001271 sm->wpa_ptk_state);
1272 return;
1273 }
1274 break;
1275 case GROUP_2:
1276 if (sm->wpa_ptk_group_state != WPA_PTK_GROUP_REKEYNEGOTIATING
1277 || !sm->PTK_valid) {
1278 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001279 "received EAPOL-Key msg 2/2 in invalid state (%d) - dropped",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001280 sm->wpa_ptk_group_state);
1281 return;
1282 }
1283 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001284 case REQUEST:
1285 break;
1286 }
1287
1288 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
1289 "received EAPOL-Key frame (%s)", msgtxt);
1290
1291 if (key_info & WPA_KEY_INFO_ACK) {
1292 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
1293 "received invalid EAPOL-Key: Key Ack set");
1294 return;
1295 }
1296
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001297 if (!wpa_key_mgmt_fils(sm->wpa_key_mgmt) &&
1298 !(key_info & WPA_KEY_INFO_MIC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001299 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
1300 "received invalid EAPOL-Key: Key MIC not set");
1301 return;
1302 }
1303
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001304#ifdef CONFIG_FILS
1305 if (wpa_key_mgmt_fils(sm->wpa_key_mgmt) &&
1306 (key_info & WPA_KEY_INFO_MIC)) {
1307 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
1308 "received invalid EAPOL-Key: Key MIC set");
1309 return;
1310 }
1311#endif /* CONFIG_FILS */
1312
Hai Shalome21d4e82020-04-29 16:34:06 -07001313 sm->MICVerified = false;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001314 if (sm->PTK_valid && !sm->update_snonce) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001315 if (mic_len &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001316 wpa_verify_key_mic(sm->wpa_key_mgmt, sm->pmk_len, &sm->PTK,
1317 data, data_len) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001318 (msg != PAIRWISE_4 || !sm->alt_snonce_valid ||
1319 wpa_try_alt_snonce(sm, data, data_len))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001320 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
1321 "received EAPOL-Key with invalid MIC");
Hai Shalom74f70d42019-02-11 14:42:39 -08001322#ifdef TEST_FUZZ
1323 wpa_printf(MSG_INFO,
1324 "TEST: Ignore Key MIC failure for fuzz testing");
1325 goto continue_fuzz;
1326#endif /* TEST_FUZZ */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001327 return;
1328 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001329#ifdef CONFIG_FILS
1330 if (!mic_len &&
1331 wpa_aead_decrypt(sm, &sm->PTK, data, data_len,
1332 &key_data_length) < 0) {
1333 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
1334 "received EAPOL-Key with invalid MIC");
Hai Shalom74f70d42019-02-11 14:42:39 -08001335#ifdef TEST_FUZZ
1336 wpa_printf(MSG_INFO,
1337 "TEST: Ignore Key MIC failure for fuzz testing");
1338 goto continue_fuzz;
1339#endif /* TEST_FUZZ */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001340 return;
1341 }
1342#endif /* CONFIG_FILS */
Hai Shalom74f70d42019-02-11 14:42:39 -08001343#ifdef TEST_FUZZ
1344 continue_fuzz:
1345#endif /* TEST_FUZZ */
Hai Shalome21d4e82020-04-29 16:34:06 -07001346 sm->MICVerified = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001347 eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm);
1348 sm->pending_1_of_4_timeout = 0;
1349 }
1350
1351 if (key_info & WPA_KEY_INFO_REQUEST) {
1352 if (sm->MICVerified) {
1353 sm->req_replay_counter_used = 1;
1354 os_memcpy(sm->req_replay_counter, key->replay_counter,
1355 WPA_REPLAY_COUNTER_LEN);
1356 } else {
1357 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001358 "received EAPOL-Key request with invalid MIC");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001359 return;
1360 }
1361
1362 /*
1363 * TODO: should decrypt key data field if encryption was used;
1364 * even though MAC address KDE is not normally encrypted,
1365 * supplicant is allowed to encrypt it.
1366 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001367 if (key_info & WPA_KEY_INFO_ERROR) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001368 if (wpa_receive_error_report(
1369 wpa_auth, sm,
1370 !(key_info & WPA_KEY_INFO_KEY_TYPE)) > 0)
1371 return; /* STA entry was removed */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001372 } else if (key_info & WPA_KEY_INFO_KEY_TYPE) {
1373 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001374 "received EAPOL-Key Request for new 4-Way Handshake");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001375 wpa_request_new_ptk(sm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001376 } else if (key_data_length > 0 &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001377 wpa_parse_kde_ies(key_data, key_data_length,
1378 &kde) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001379 kde.mac_addr) {
1380 } else {
1381 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001382 "received EAPOL-Key Request for GTK rekeying");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001383 eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL);
Hai Shaloma20dcd72022-02-04 13:43:00 -08001384 if (wpa_auth_gtk_rekey_in_process(wpa_auth))
1385 wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG,
1386 "skip new GTK rekey - already in process");
1387 else
1388 wpa_rekey_gtk(wpa_auth, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001389 }
1390 } else {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001391 /* Do not allow the same key replay counter to be reused. */
1392 wpa_replay_counter_mark_invalid(sm->key_replay,
1393 key->replay_counter);
1394
1395 if (msg == PAIRWISE_2) {
1396 /*
1397 * Maintain a copy of the pending EAPOL-Key frames in
1398 * case the EAPOL-Key frame was retransmitted. This is
1399 * needed to allow EAPOL-Key msg 2/4 reply to another
1400 * pending msg 1/4 to update the SNonce to work around
1401 * unexpected supplicant behavior.
1402 */
1403 os_memcpy(sm->prev_key_replay, sm->key_replay,
1404 sizeof(sm->key_replay));
1405 } else {
1406 os_memset(sm->prev_key_replay, 0,
1407 sizeof(sm->prev_key_replay));
1408 }
1409
1410 /*
1411 * Make sure old valid counters are not accepted anymore and
1412 * do not get copied again.
1413 */
1414 wpa_replay_counter_mark_invalid(sm->key_replay, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001415 }
1416
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001417 os_free(sm->last_rx_eapol_key);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001418 sm->last_rx_eapol_key = os_memdup(data, data_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07001419 if (!sm->last_rx_eapol_key)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001420 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001421 sm->last_rx_eapol_key_len = data_len;
1422
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001423 sm->rx_eapol_key_secure = !!(key_info & WPA_KEY_INFO_SECURE);
Hai Shalome21d4e82020-04-29 16:34:06 -07001424 sm->EAPOLKeyReceived = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001425 sm->EAPOLKeyPairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE);
1426 sm->EAPOLKeyRequest = !!(key_info & WPA_KEY_INFO_REQUEST);
1427 os_memcpy(sm->SNonce, key->key_nonce, WPA_NONCE_LEN);
1428 wpa_sm_step(sm);
1429}
1430
1431
1432static int wpa_gmk_to_gtk(const u8 *gmk, const char *label, const u8 *addr,
1433 const u8 *gnonce, u8 *gtk, size_t gtk_len)
1434{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001435 u8 data[ETH_ALEN + WPA_NONCE_LEN + 8 + WPA_GTK_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001436 u8 *pos;
1437 int ret = 0;
1438
1439 /* GTK = PRF-X(GMK, "Group key expansion",
1440 * AA || GNonce || Time || random data)
1441 * The example described in the IEEE 802.11 standard uses only AA and
1442 * GNonce as inputs here. Add some more entropy since this derivation
1443 * is done only at the Authenticator and as such, does not need to be
1444 * exactly same.
1445 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001446 os_memset(data, 0, sizeof(data));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001447 os_memcpy(data, addr, ETH_ALEN);
1448 os_memcpy(data + ETH_ALEN, gnonce, WPA_NONCE_LEN);
1449 pos = data + ETH_ALEN + WPA_NONCE_LEN;
1450 wpa_get_ntp_timestamp(pos);
Hai Shalom74f70d42019-02-11 14:42:39 -08001451#ifdef TEST_FUZZ
1452 os_memset(pos, 0xef, 8);
1453#endif /* TEST_FUZZ */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001454 pos += 8;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001455 if (random_get_bytes(pos, gtk_len) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001456 ret = -1;
1457
Roshan Pius3a1667e2018-07-03 15:17:14 -07001458#ifdef CONFIG_SHA384
1459 if (sha384_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data),
1460 gtk, gtk_len) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001461 ret = -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001462#else /* CONFIG_SHA384 */
1463#ifdef CONFIG_SHA256
1464 if (sha256_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data),
1465 gtk, gtk_len) < 0)
1466 ret = -1;
1467#else /* CONFIG_SHA256 */
1468 if (sha1_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data),
1469 gtk, gtk_len) < 0)
1470 ret = -1;
1471#endif /* CONFIG_SHA256 */
1472#endif /* CONFIG_SHA384 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001473
Hai Shalom81f62d82019-07-22 12:10:00 -07001474 forced_memzero(data, sizeof(data));
1475
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001476 return ret;
1477}
1478
1479
1480static void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx)
1481{
1482 struct wpa_authenticator *wpa_auth = eloop_ctx;
1483 struct wpa_state_machine *sm = timeout_ctx;
1484
Sunil Ravia04bd252022-05-02 22:54:18 -07001485 if (sm->waiting_radius_psk) {
1486 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
1487 "Ignore EAPOL-Key timeout while waiting for RADIUS PSK");
1488 return;
1489 }
1490
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001491 sm->pending_1_of_4_timeout = 0;
1492 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "EAPOL-Key timeout");
Hai Shalome21d4e82020-04-29 16:34:06 -07001493 sm->TimeoutEvt = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001494 wpa_sm_step(sm);
1495}
1496
1497
1498void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
1499 struct wpa_state_machine *sm, int key_info,
1500 const u8 *key_rsc, const u8 *nonce,
1501 const u8 *kde, size_t kde_len,
1502 int keyidx, int encr, int force_version)
1503{
Hai Shalomfdcde762020-04-02 11:19:20 -07001504 struct wpa_auth_config *conf = &wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001505 struct ieee802_1x_hdr *hdr;
1506 struct wpa_eapol_key *key;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001507 size_t len, mic_len, keyhdrlen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001508 int alg;
1509 int key_data_len, pad_len = 0;
1510 u8 *buf, *pos;
1511 int version, pairwise;
1512 int i;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001513 u8 *key_mic, *key_data;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001514
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001515 mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001516 keyhdrlen = sizeof(*key) + mic_len + 2;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001517
1518 len = sizeof(struct ieee802_1x_hdr) + keyhdrlen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001519
1520 if (force_version)
1521 version = force_version;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001522 else if (wpa_use_akm_defined(sm->wpa_key_mgmt))
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001523 version = WPA_KEY_INFO_TYPE_AKM_DEFINED;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001524 else if (wpa_use_cmac(sm->wpa_key_mgmt))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001525 version = WPA_KEY_INFO_TYPE_AES_128_CMAC;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001526 else if (sm->pairwise != WPA_CIPHER_TKIP)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001527 version = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;
1528 else
1529 version = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
1530
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001531 pairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001532
Hai Shalomfdcde762020-04-02 11:19:20 -07001533 wpa_printf(MSG_DEBUG,
1534 "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 -07001535 version,
1536 (key_info & WPA_KEY_INFO_SECURE) ? 1 : 0,
1537 (key_info & WPA_KEY_INFO_MIC) ? 1 : 0,
1538 (key_info & WPA_KEY_INFO_ACK) ? 1 : 0,
1539 (key_info & WPA_KEY_INFO_INSTALL) ? 1 : 0,
Hai Shalomfdcde762020-04-02 11:19:20 -07001540 pairwise, kde_len, keyidx, encr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001541
1542 key_data_len = kde_len;
1543
1544 if ((version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
Roshan Pius3a1667e2018-07-03 15:17:14 -07001545 wpa_use_aes_key_wrap(sm->wpa_key_mgmt) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001546 version == WPA_KEY_INFO_TYPE_AES_128_CMAC) && encr) {
1547 pad_len = key_data_len % 8;
1548 if (pad_len)
1549 pad_len = 8 - pad_len;
1550 key_data_len += pad_len + 8;
1551 }
1552
1553 len += key_data_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001554 if (!mic_len && encr)
1555 len += AES_BLOCK_SIZE;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001556
1557 hdr = os_zalloc(len);
Hai Shalomfdcde762020-04-02 11:19:20 -07001558 if (!hdr)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001559 return;
Hai Shalomfdcde762020-04-02 11:19:20 -07001560 hdr->version = conf->eapol_version;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001561 hdr->type = IEEE802_1X_TYPE_EAPOL_KEY;
1562 hdr->length = host_to_be16(len - sizeof(*hdr));
1563 key = (struct wpa_eapol_key *) (hdr + 1);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001564 key_mic = (u8 *) (key + 1);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001565 key_data = ((u8 *) (hdr + 1)) + keyhdrlen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001566
1567 key->type = sm->wpa == WPA_VERSION_WPA2 ?
1568 EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
1569 key_info |= version;
1570 if (encr && sm->wpa == WPA_VERSION_WPA2)
1571 key_info |= WPA_KEY_INFO_ENCR_KEY_DATA;
1572 if (sm->wpa != WPA_VERSION_WPA2)
1573 key_info |= keyidx << WPA_KEY_INFO_KEY_INDEX_SHIFT;
1574 WPA_PUT_BE16(key->key_info, key_info);
1575
Hai Shalomfdcde762020-04-02 11:19:20 -07001576 alg = pairwise ? sm->pairwise : conf->wpa_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001577 if (sm->wpa == WPA_VERSION_WPA2 && !pairwise)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001578 WPA_PUT_BE16(key->key_length, 0);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001579 else
1580 WPA_PUT_BE16(key->key_length, wpa_cipher_key_len(alg));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001581
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001582 for (i = RSNA_MAX_EAPOL_RETRIES - 1; i > 0; i--) {
1583 sm->key_replay[i].valid = sm->key_replay[i - 1].valid;
1584 os_memcpy(sm->key_replay[i].counter,
1585 sm->key_replay[i - 1].counter,
1586 WPA_REPLAY_COUNTER_LEN);
1587 }
1588 inc_byte_array(sm->key_replay[0].counter, WPA_REPLAY_COUNTER_LEN);
1589 os_memcpy(key->replay_counter, sm->key_replay[0].counter,
1590 WPA_REPLAY_COUNTER_LEN);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001591 wpa_hexdump(MSG_DEBUG, "WPA: Replay Counter",
1592 key->replay_counter, WPA_REPLAY_COUNTER_LEN);
Hai Shalome21d4e82020-04-29 16:34:06 -07001593 sm->key_replay[0].valid = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001594
1595 if (nonce)
1596 os_memcpy(key->key_nonce, nonce, WPA_NONCE_LEN);
1597
1598 if (key_rsc)
1599 os_memcpy(key->key_rsc, key_rsc, WPA_KEY_RSC_LEN);
1600
1601 if (kde && !encr) {
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001602 os_memcpy(key_data, kde, kde_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001603 WPA_PUT_BE16(key_mic + mic_len, kde_len);
1604#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07001605 } else if (!mic_len && kde) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001606 const u8 *aad[1];
1607 size_t aad_len[1];
1608
1609 WPA_PUT_BE16(key_mic, AES_BLOCK_SIZE + kde_len);
1610 wpa_hexdump_key(MSG_DEBUG, "Plaintext EAPOL-Key Key Data",
1611 kde, kde_len);
1612
1613 wpa_hexdump_key(MSG_DEBUG, "WPA: KEK",
1614 sm->PTK.kek, sm->PTK.kek_len);
1615 /* AES-SIV AAD from EAPOL protocol version field (inclusive) to
1616 * to Key Data (exclusive). */
1617 aad[0] = (u8 *) hdr;
1618 aad_len[0] = key_mic + 2 - (u8 *) hdr;
1619 if (aes_siv_encrypt(sm->PTK.kek, sm->PTK.kek_len, kde, kde_len,
1620 1, aad, aad_len, key_mic + 2) < 0) {
1621 wpa_printf(MSG_DEBUG, "WPA: AES-SIV encryption failed");
1622 return;
1623 }
1624
1625 wpa_hexdump(MSG_DEBUG, "WPA: Encrypted Key Data from SIV",
1626 key_mic + 2, AES_BLOCK_SIZE + kde_len);
1627#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001628 } else if (encr && kde) {
1629 buf = os_zalloc(key_data_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07001630 if (!buf) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001631 os_free(hdr);
1632 return;
1633 }
1634 pos = buf;
1635 os_memcpy(pos, kde, kde_len);
1636 pos += kde_len;
1637
1638 if (pad_len)
1639 *pos++ = 0xdd;
1640
1641 wpa_hexdump_key(MSG_DEBUG, "Plaintext EAPOL-Key Key Data",
1642 buf, key_data_len);
1643 if (version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
Roshan Pius3a1667e2018-07-03 15:17:14 -07001644 wpa_use_aes_key_wrap(sm->wpa_key_mgmt) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001645 version == WPA_KEY_INFO_TYPE_AES_128_CMAC) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001646 wpa_printf(MSG_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07001647 "WPA: Encrypt Key Data using AES-WRAP (KEK length %zu)",
1648 sm->PTK.kek_len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001649 if (aes_wrap(sm->PTK.kek, sm->PTK.kek_len,
1650 (key_data_len - 8) / 8, buf, key_data)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001651 os_free(hdr);
Sunil Ravia04bd252022-05-02 22:54:18 -07001652 bin_clear_free(buf, key_data_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001653 return;
1654 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001655 WPA_PUT_BE16(key_mic + mic_len, key_data_len);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001656#ifndef CONFIG_NO_RC4
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001657 } else if (sm->PTK.kek_len == 16) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001658 u8 ek[32];
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001659
1660 wpa_printf(MSG_DEBUG,
1661 "WPA: Encrypt Key Data using RC4");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001662 os_memcpy(key->key_iv,
1663 sm->group->Counter + WPA_NONCE_LEN - 16, 16);
1664 inc_byte_array(sm->group->Counter, WPA_NONCE_LEN);
1665 os_memcpy(ek, key->key_iv, 16);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001666 os_memcpy(ek + 16, sm->PTK.kek, sm->PTK.kek_len);
1667 os_memcpy(key_data, buf, key_data_len);
1668 rc4_skip(ek, 32, 256, key_data, key_data_len);
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#endif /* CONFIG_NO_RC4 */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001671 } else {
1672 os_free(hdr);
Sunil Ravia04bd252022-05-02 22:54:18 -07001673 bin_clear_free(buf, key_data_len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001674 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001675 }
Sunil Ravia04bd252022-05-02 22:54:18 -07001676 bin_clear_free(buf, key_data_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001677 }
1678
1679 if (key_info & WPA_KEY_INFO_MIC) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001680 if (!sm->PTK_valid || !mic_len) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001681 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07001682 "PTK not valid when sending EAPOL-Key frame");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001683 os_free(hdr);
1684 return;
1685 }
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001686
Roshan Pius3a1667e2018-07-03 15:17:14 -07001687 if (wpa_eapol_key_mic(sm->PTK.kck, sm->PTK.kck_len,
1688 sm->wpa_key_mgmt, version,
1689 (u8 *) hdr, len, key_mic) < 0) {
1690 os_free(hdr);
1691 return;
1692 }
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001693#ifdef CONFIG_TESTING_OPTIONS
1694 if (!pairwise &&
Hai Shalomfdcde762020-04-02 11:19:20 -07001695 conf->corrupt_gtk_rekey_mic_probability > 0.0 &&
1696 drand48() < conf->corrupt_gtk_rekey_mic_probability) {
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001697 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
1698 "Corrupting group EAPOL-Key Key MIC");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001699 key_mic[0]++;
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001700 }
1701#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001702 }
1703
Hai Shalomfdcde762020-04-02 11:19:20 -07001704 wpa_auth_set_eapol(wpa_auth, sm->addr, WPA_EAPOL_inc_EapolFramesTx, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001705 wpa_auth_send_eapol(wpa_auth, sm->addr, (u8 *) hdr, len,
Kai Shie75b0652020-11-24 20:31:29 -08001706 sm->pairwise_set);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001707 os_free(hdr);
1708}
1709
1710
1711static void wpa_send_eapol(struct wpa_authenticator *wpa_auth,
1712 struct wpa_state_machine *sm, int key_info,
1713 const u8 *key_rsc, const u8 *nonce,
1714 const u8 *kde, size_t kde_len,
1715 int keyidx, int encr)
1716{
1717 int timeout_ms;
1718 int pairwise = key_info & WPA_KEY_INFO_KEY_TYPE;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001719 u32 ctr;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001720
Hai Shalomfdcde762020-04-02 11:19:20 -07001721 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001722 return;
1723
1724 __wpa_send_eapol(wpa_auth, sm, key_info, key_rsc, nonce, kde, kde_len,
1725 keyidx, encr, 0);
1726
1727 ctr = pairwise ? sm->TimeoutCtr : sm->GTimeoutCtr;
1728 if (ctr == 1 && wpa_auth->conf.tx_status)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001729 timeout_ms = pairwise ? eapol_key_timeout_first :
1730 eapol_key_timeout_first_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001731 else
1732 timeout_ms = eapol_key_timeout_subseq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001733 if (wpa_auth->conf.wpa_disable_eapol_key_retries &&
1734 (!pairwise || (key_info & WPA_KEY_INFO_MIC)))
1735 timeout_ms = eapol_key_timeout_no_retrans;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001736 if (pairwise && ctr == 1 && !(key_info & WPA_KEY_INFO_MIC))
1737 sm->pending_1_of_4_timeout = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08001738#ifdef TEST_FUZZ
1739 timeout_ms = 1;
1740#endif /* TEST_FUZZ */
Kai Shie75b0652020-11-24 20:31:29 -08001741#ifdef CONFIG_TESTING_OPTIONS
1742 if(wpa_auth->conf.enable_eapol_large_timeout) {
1743 timeout_ms = 50 * 1000;
1744 }
1745#endif
Hai Shalomfdcde762020-04-02 11:19:20 -07001746 wpa_printf(MSG_DEBUG,
1747 "WPA: Use EAPOL-Key timeout of %u ms (retry counter %u)",
1748 timeout_ms, ctr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001749 eloop_register_timeout(timeout_ms / 1000, (timeout_ms % 1000) * 1000,
1750 wpa_send_eapol_timeout, wpa_auth, sm);
1751}
1752
1753
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001754static int wpa_verify_key_mic(int akmp, size_t pmk_len, struct wpa_ptk *PTK,
1755 u8 *data, size_t data_len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001756{
1757 struct ieee802_1x_hdr *hdr;
1758 struct wpa_eapol_key *key;
1759 u16 key_info;
1760 int ret = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001761 u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN], *mic_pos;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001762 size_t mic_len = wpa_mic_len(akmp, pmk_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001763
1764 if (data_len < sizeof(*hdr) + sizeof(*key))
1765 return -1;
1766
1767 hdr = (struct ieee802_1x_hdr *) data;
1768 key = (struct wpa_eapol_key *) (hdr + 1);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001769 mic_pos = (u8 *) (key + 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001770 key_info = WPA_GET_BE16(key->key_info);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001771 os_memcpy(mic, mic_pos, mic_len);
1772 os_memset(mic_pos, 0, mic_len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001773 if (wpa_eapol_key_mic(PTK->kck, PTK->kck_len, akmp,
1774 key_info & WPA_KEY_INFO_TYPE_MASK,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001775 data, data_len, mic_pos) ||
1776 os_memcmp_const(mic, mic_pos, mic_len) != 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001777 ret = -1;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001778 os_memcpy(mic_pos, mic, mic_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001779 return ret;
1780}
1781
1782
1783void wpa_remove_ptk(struct wpa_state_machine *sm)
1784{
Hai Shalome21d4e82020-04-29 16:34:06 -07001785 sm->PTK_valid = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001786 os_memset(&sm->PTK, 0, sizeof(sm->PTK));
Hai Shalom60840252021-02-19 19:02:11 -08001787
1788 wpa_auth_remove_ptksa(sm->wpa_auth, sm->addr, sm->pairwise);
1789
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001790 if (wpa_auth_set_key(sm->wpa_auth, 0, WPA_ALG_NONE, sm->addr, 0, NULL,
Hai Shalomfdcde762020-04-02 11:19:20 -07001791 0, KEY_FLAG_PAIRWISE))
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001792 wpa_printf(MSG_DEBUG,
1793 "RSN: PTK removal from the driver failed");
Hai Shalomfdcde762020-04-02 11:19:20 -07001794 if (sm->use_ext_key_id &&
1795 wpa_auth_set_key(sm->wpa_auth, 0, WPA_ALG_NONE, sm->addr, 1, NULL,
1796 0, KEY_FLAG_PAIRWISE))
1797 wpa_printf(MSG_DEBUG,
1798 "RSN: PTK Key ID 1 removal from the driver failed");
Hai Shalome21d4e82020-04-29 16:34:06 -07001799 sm->pairwise_set = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001800 eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm);
1801}
1802
1803
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001804int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001805{
1806 int remove_ptk = 1;
1807
Hai Shalomfdcde762020-04-02 11:19:20 -07001808 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001809 return -1;
1810
1811 wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
1812 "event %d notification", event);
1813
1814 switch (event) {
1815 case WPA_AUTH:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001816#ifdef CONFIG_MESH
1817 /* PTKs are derived through AMPE */
1818 if (wpa_auth_start_ampe(sm->wpa_auth, sm->addr)) {
1819 /* not mesh */
1820 break;
1821 }
1822 return 0;
1823#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001824 case WPA_ASSOC:
1825 break;
1826 case WPA_DEAUTH:
1827 case WPA_DISASSOC:
Hai Shalome21d4e82020-04-29 16:34:06 -07001828 sm->DeauthenticationRequest = true;
Hai Shalom1dc4d202019-04-29 16:22:27 -07001829 os_memset(sm->PMK, 0, sizeof(sm->PMK));
1830 sm->pmk_len = 0;
Sunil Ravia04bd252022-05-02 22:54:18 -07001831#ifdef CONFIG_IEEE80211R_AP
Hai Shalom1dc4d202019-04-29 16:22:27 -07001832 os_memset(sm->xxkey, 0, sizeof(sm->xxkey));
1833 sm->xxkey_len = 0;
Hai Shalom81f62d82019-07-22 12:10:00 -07001834 os_memset(sm->pmk_r1, 0, sizeof(sm->pmk_r1));
1835 sm->pmk_r1_len = 0;
Hai Shalom1dc4d202019-04-29 16:22:27 -07001836#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001837 break;
1838 case WPA_REAUTH:
1839 case WPA_REAUTH_EAPOL:
1840 if (!sm->started) {
1841 /*
1842 * When using WPS, we may end up here if the STA
1843 * manages to re-associate without the previous STA
1844 * entry getting removed. Consequently, we need to make
1845 * sure that the WPA state machines gets initialized
1846 * properly at this point.
1847 */
Hai Shalomfdcde762020-04-02 11:19:20 -07001848 wpa_printf(MSG_DEBUG,
1849 "WPA state machine had not been started - initialize now");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001850 sm->started = 1;
Hai Shalome21d4e82020-04-29 16:34:06 -07001851 sm->Init = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001852 if (wpa_sm_step(sm) == 1)
1853 return 1; /* should not really happen */
Hai Shalome21d4e82020-04-29 16:34:06 -07001854 sm->Init = false;
1855 sm->AuthenticationRequest = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001856 break;
1857 }
Hai Shalomfdcde762020-04-02 11:19:20 -07001858
Sunil Ravia04bd252022-05-02 22:54:18 -07001859 if (sm->ptkstart_without_success > 3) {
1860 wpa_printf(MSG_INFO,
1861 "WPA: Multiple EAP reauth attempts without 4-way handshake completion, disconnect "
1862 MACSTR, MAC2STR(sm->addr));
1863 sm->Disconnect = true;
1864 break;
1865 }
1866
Hai Shalomfdcde762020-04-02 11:19:20 -07001867 if (!sm->use_ext_key_id &&
1868 sm->wpa_auth->conf.wpa_deny_ptk0_rekey) {
1869 wpa_printf(MSG_INFO,
1870 "WPA: PTK0 rekey not allowed, disconnect "
1871 MACSTR, MAC2STR(sm->addr));
Hai Shalome21d4e82020-04-29 16:34:06 -07001872 sm->Disconnect = true;
Hai Shalomfdcde762020-04-02 11:19:20 -07001873 /* Try to encourage the STA to reconnect */
1874 sm->disconnect_reason =
1875 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA;
1876 break;
1877 }
1878
1879 if (sm->use_ext_key_id)
1880 sm->keyidx_active ^= 1; /* flip Key ID */
1881
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001882 if (sm->GUpdateStationKeys) {
1883 /*
1884 * Reauthentication cancels the pending group key
1885 * update for this STA.
1886 */
1887 sm->group->GKeyDoneStations--;
Hai Shalome21d4e82020-04-29 16:34:06 -07001888 sm->GUpdateStationKeys = false;
1889 sm->PtkGroupInit = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001890 }
Hai Shalome21d4e82020-04-29 16:34:06 -07001891 sm->ReAuthenticationRequest = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001892 break;
1893 case WPA_ASSOC_FT:
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001894#ifdef CONFIG_IEEE80211R_AP
Hai Shalomfdcde762020-04-02 11:19:20 -07001895 wpa_printf(MSG_DEBUG,
1896 "FT: Retry PTK configuration after association");
Hai Shalomb755a2a2020-04-23 21:49:02 -07001897 wpa_ft_install_ptk(sm, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001898
1899 /* Using FT protocol, not WPA auth state machine */
1900 sm->ft_completed = 1;
Hai Shalom81f62d82019-07-22 12:10:00 -07001901 wpa_auth_set_ptk_rekey_timer(sm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001902 return 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001903#else /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001904 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001905#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001906 case WPA_ASSOC_FILS:
1907#ifdef CONFIG_FILS
1908 wpa_printf(MSG_DEBUG,
1909 "FILS: TK configuration after association");
1910 fils_set_tk(sm);
1911 sm->fils_completed = 1;
1912 return 0;
1913#else /* CONFIG_FILS */
1914 break;
1915#endif /* CONFIG_FILS */
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02001916 case WPA_DRV_STA_REMOVED:
Hai Shalome21d4e82020-04-29 16:34:06 -07001917 sm->tk_already_set = false;
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02001918 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001919 }
1920
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001921#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001922 sm->ft_completed = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001923#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001924
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001925 if (sm->mgmt_frame_prot && event == WPA_AUTH)
1926 remove_ptk = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001927#ifdef CONFIG_FILS
1928 if (wpa_key_mgmt_fils(sm->wpa_key_mgmt) &&
1929 (event == WPA_AUTH || event == WPA_ASSOC))
1930 remove_ptk = 0;
1931#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001932
1933 if (remove_ptk) {
Hai Shalome21d4e82020-04-29 16:34:06 -07001934 sm->PTK_valid = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001935 os_memset(&sm->PTK, 0, sizeof(sm->PTK));
1936
1937 if (event != WPA_REAUTH_EAPOL)
1938 wpa_remove_ptk(sm);
1939 }
1940
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001941 if (sm->in_step_loop) {
1942 /*
1943 * wpa_sm_step() is already running - avoid recursive call to
1944 * it by making the existing loop process the new update.
1945 */
Hai Shalome21d4e82020-04-29 16:34:06 -07001946 sm->changed = true;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001947 return 0;
1948 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001949 return wpa_sm_step(sm);
1950}
1951
1952
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001953SM_STATE(WPA_PTK, INITIALIZE)
1954{
1955 SM_ENTRY_MA(WPA_PTK, INITIALIZE, wpa_ptk);
1956 if (sm->Init) {
1957 /* Init flag is not cleared here, so avoid busy
1958 * loop by claiming nothing changed. */
Hai Shalome21d4e82020-04-29 16:34:06 -07001959 sm->changed = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001960 }
1961
1962 sm->keycount = 0;
1963 if (sm->GUpdateStationKeys)
1964 sm->group->GKeyDoneStations--;
Hai Shalome21d4e82020-04-29 16:34:06 -07001965 sm->GUpdateStationKeys = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001966 if (sm->wpa == WPA_VERSION_WPA)
Hai Shalome21d4e82020-04-29 16:34:06 -07001967 sm->PInitAKeys = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001968 if (1 /* Unicast cipher supported AND (ESS OR ((IBSS or WDS) and
1969 * Local AA > Remote AA)) */) {
Hai Shalome21d4e82020-04-29 16:34:06 -07001970 sm->Pair = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001971 }
1972 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 0);
1973 wpa_remove_ptk(sm);
1974 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid, 0);
1975 sm->TimeoutCtr = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001976 if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
1977 sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP ||
1978 sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001979 wpa_auth_set_eapol(sm->wpa_auth, sm->addr,
1980 WPA_EAPOL_authorized, 0);
1981 }
1982}
1983
1984
1985SM_STATE(WPA_PTK, DISCONNECT)
1986{
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001987 u16 reason = sm->disconnect_reason;
1988
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001989 SM_ENTRY_MA(WPA_PTK, DISCONNECT, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07001990 sm->Disconnect = false;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001991 sm->disconnect_reason = 0;
1992 if (!reason)
1993 reason = WLAN_REASON_PREV_AUTH_NOT_VALID;
1994 wpa_sta_disconnect(sm->wpa_auth, sm->addr, reason);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001995}
1996
1997
1998SM_STATE(WPA_PTK, DISCONNECTED)
1999{
2000 SM_ENTRY_MA(WPA_PTK, DISCONNECTED, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07002001 sm->DeauthenticationRequest = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002002}
2003
2004
2005SM_STATE(WPA_PTK, AUTHENTICATION)
2006{
2007 SM_ENTRY_MA(WPA_PTK, AUTHENTICATION, wpa_ptk);
2008 os_memset(&sm->PTK, 0, sizeof(sm->PTK));
Hai Shalome21d4e82020-04-29 16:34:06 -07002009 sm->PTK_valid = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002010 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portControl_Auto,
2011 1);
2012 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 1);
Hai Shalome21d4e82020-04-29 16:34:06 -07002013 sm->AuthenticationRequest = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002014}
2015
2016
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002017static void wpa_group_ensure_init(struct wpa_authenticator *wpa_auth,
2018 struct wpa_group *group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002019{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002020 if (group->first_sta_seen)
2021 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002022 /*
2023 * System has run bit further than at the time hostapd was started
2024 * potentially very early during boot up. This provides better chances
2025 * of collecting more randomness on embedded systems. Re-initialize the
2026 * GMK and Counter here to improve their strength if there was not
2027 * enough entropy available immediately after system startup.
2028 */
Hai Shalomfdcde762020-04-02 11:19:20 -07002029 wpa_printf(MSG_DEBUG,
2030 "WPA: Re-initialize GMK/Counter on first station");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002031 if (random_pool_ready() != 1) {
Hai Shalomfdcde762020-04-02 11:19:20 -07002032 wpa_printf(MSG_INFO,
2033 "WPA: Not enough entropy in random pool to proceed - reject first 4-way handshake");
Hai Shalome21d4e82020-04-29 16:34:06 -07002034 group->reject_4way_hs_for_entropy = true;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002035 } else {
Hai Shalome21d4e82020-04-29 16:34:06 -07002036 group->first_sta_seen = true;
2037 group->reject_4way_hs_for_entropy = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002038 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002039
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002040 if (wpa_group_init_gmk_and_counter(wpa_auth, group) < 0 ||
2041 wpa_gtk_update(wpa_auth, group) < 0 ||
2042 wpa_group_config_group_keys(wpa_auth, group) < 0) {
2043 wpa_printf(MSG_INFO, "WPA: GMK/GTK setup failed");
Hai Shalome21d4e82020-04-29 16:34:06 -07002044 group->first_sta_seen = false;
2045 group->reject_4way_hs_for_entropy = true;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002046 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002047}
2048
2049
2050SM_STATE(WPA_PTK, AUTHENTICATION2)
2051{
2052 SM_ENTRY_MA(WPA_PTK, AUTHENTICATION2, wpa_ptk);
2053
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002054 wpa_group_ensure_init(sm->wpa_auth, sm->group);
Hai Shalome21d4e82020-04-29 16:34:06 -07002055 sm->ReAuthenticationRequest = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002056
Dmitry Shmidt04949592012-07-19 12:16:46 -07002057 /*
2058 * Definition of ANonce selection in IEEE Std 802.11i-2004 is somewhat
2059 * ambiguous. The Authenticator state machine uses a counter that is
2060 * incremented by one for each 4-way handshake. However, the security
2061 * analysis of 4-way handshake points out that unpredictable nonces
2062 * help in preventing precomputation attacks. Instead of the state
2063 * machine definition, use an unpredictable nonce value here to provide
2064 * stronger protection against potential precomputation attacks.
2065 */
2066 if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) {
Hai Shalomfdcde762020-04-02 11:19:20 -07002067 wpa_printf(MSG_ERROR,
2068 "WPA: Failed to get random data for ANonce.");
Hai Shalome21d4e82020-04-29 16:34:06 -07002069 sm->Disconnect = true;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002070 return;
2071 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002072 wpa_hexdump(MSG_DEBUG, "WPA: Assign ANonce", sm->ANonce,
2073 WPA_NONCE_LEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002074 /* IEEE 802.11i does not clear TimeoutCtr here, but this is more
2075 * logical place than INITIALIZE since AUTHENTICATION2 can be
2076 * re-entered on ReAuthenticationRequest without going through
2077 * INITIALIZE. */
2078 sm->TimeoutCtr = 0;
2079}
2080
2081
Jouni Malinen1420a892017-10-01 12:32:57 +03002082static int wpa_auth_sm_ptk_update(struct wpa_state_machine *sm)
2083{
2084 if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) {
2085 wpa_printf(MSG_ERROR,
2086 "WPA: Failed to get random data for ANonce");
Hai Shalome21d4e82020-04-29 16:34:06 -07002087 sm->Disconnect = true;
Jouni Malinen1420a892017-10-01 12:32:57 +03002088 return -1;
2089 }
2090 wpa_hexdump(MSG_DEBUG, "WPA: Assign new ANonce", sm->ANonce,
2091 WPA_NONCE_LEN);
2092 sm->TimeoutCtr = 0;
2093 return 0;
2094}
2095
2096
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002097SM_STATE(WPA_PTK, INITPMK)
2098{
2099 u8 msk[2 * PMK_LEN];
2100 size_t len = 2 * PMK_LEN;
2101
2102 SM_ENTRY_MA(WPA_PTK, INITPMK, wpa_ptk);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002103#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002104 sm->xxkey_len = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002105#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002106 if (sm->pmksa) {
2107 wpa_printf(MSG_DEBUG, "WPA: PMK from PMKSA cache");
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002108 os_memcpy(sm->PMK, sm->pmksa->pmk, sm->pmksa->pmk_len);
2109 sm->pmk_len = sm->pmksa->pmk_len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002110#ifdef CONFIG_DPP
2111 } else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP) {
2112 wpa_printf(MSG_DEBUG,
2113 "DPP: No PMKSA cache entry for STA - reject connection");
Hai Shalome21d4e82020-04-29 16:34:06 -07002114 sm->Disconnect = true;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002115 sm->disconnect_reason = WLAN_REASON_INVALID_PMKID;
2116 return;
2117#endif /* CONFIG_DPP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002118 } else if (wpa_auth_get_msk(sm->wpa_auth, sm->addr, msk, &len) == 0) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002119 unsigned int pmk_len;
2120
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002121 if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002122 pmk_len = PMK_LEN_SUITE_B_192;
2123 else
2124 pmk_len = PMK_LEN;
Hai Shalomfdcde762020-04-02 11:19:20 -07002125 wpa_printf(MSG_DEBUG,
2126 "WPA: PMK from EAPOL state machine (MSK len=%zu PMK len=%u)",
2127 len, pmk_len);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002128 if (len < pmk_len) {
2129 wpa_printf(MSG_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07002130 "WPA: MSK not long enough (%zu) to create PMK (%u)",
2131 len, pmk_len);
Hai Shalome21d4e82020-04-29 16:34:06 -07002132 sm->Disconnect = true;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002133 return;
2134 }
2135 os_memcpy(sm->PMK, msk, pmk_len);
2136 sm->pmk_len = pmk_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002137#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002138 if (len >= 2 * PMK_LEN) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002139 if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) {
2140 os_memcpy(sm->xxkey, msk, SHA384_MAC_LEN);
2141 sm->xxkey_len = SHA384_MAC_LEN;
2142 } else {
2143 os_memcpy(sm->xxkey, msk + PMK_LEN, PMK_LEN);
2144 sm->xxkey_len = PMK_LEN;
2145 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002146 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002147#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002148 } else {
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002149 wpa_printf(MSG_DEBUG, "WPA: Could not get PMK, get_msk: %p",
Paul Stewart092955c2017-02-06 09:13:09 -08002150 sm->wpa_auth->cb->get_msk);
Hai Shalome21d4e82020-04-29 16:34:06 -07002151 sm->Disconnect = true;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002152 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002153 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002154 forced_memzero(msk, sizeof(msk));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002155
2156 sm->req_replay_counter_used = 0;
Hai Shalome21d4e82020-04-29 16:34:06 -07002157 /* IEEE 802.11i does not set keyRun to false, but not doing this
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002158 * will break reauthentication since EAPOL state machines may not be
2159 * get into AUTHENTICATING state that clears keyRun before WPA state
2160 * machine enters AUTHENTICATION2 state and goes immediately to INITPMK
2161 * state and takes PMK from the previously used AAA Key. This will
2162 * eventually fail in 4-Way Handshake because Supplicant uses PMK
Hai Shalome21d4e82020-04-29 16:34:06 -07002163 * derived from the new AAA Key. Setting keyRun = false here seems to
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002164 * be good workaround for this issue. */
Hai Shalome21d4e82020-04-29 16:34:06 -07002165 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyRun, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002166}
2167
2168
2169SM_STATE(WPA_PTK, INITPSK)
2170{
2171 const u8 *psk;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002172 size_t psk_len;
2173
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002174 SM_ENTRY_MA(WPA_PTK, INITPSK, wpa_ptk);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002175 psk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr, NULL,
Hai Shalom021b0b52019-04-10 11:17:58 -07002176 &psk_len, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002177 if (psk) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002178 os_memcpy(sm->PMK, psk, psk_len);
2179 sm->pmk_len = psk_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002180#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002181 os_memcpy(sm->xxkey, psk, PMK_LEN);
2182 sm->xxkey_len = PMK_LEN;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002183#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002184 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002185#ifdef CONFIG_SAE
2186 if (wpa_auth_uses_sae(sm) && sm->pmksa) {
2187 wpa_printf(MSG_DEBUG, "SAE: PMK from PMKSA cache");
2188 os_memcpy(sm->PMK, sm->pmksa->pmk, sm->pmksa->pmk_len);
2189 sm->pmk_len = sm->pmksa->pmk_len;
Hai Shalom021b0b52019-04-10 11:17:58 -07002190#ifdef CONFIG_IEEE80211R_AP
2191 os_memcpy(sm->xxkey, sm->pmksa->pmk, sm->pmksa->pmk_len);
2192 sm->xxkey_len = sm->pmksa->pmk_len;
2193#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002194 }
2195#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002196 sm->req_replay_counter_used = 0;
2197}
2198
2199
2200SM_STATE(WPA_PTK, PTKSTART)
2201{
2202 u8 buf[2 + RSN_SELECTOR_LEN + PMKID_LEN], *pmkid = NULL;
2203 size_t pmkid_len = 0;
Sunil8cd6f4d2022-06-28 18:40:46 +00002204 u16 key_info;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002205
2206 SM_ENTRY_MA(WPA_PTK, PTKSTART, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07002207 sm->PTKRequest = false;
2208 sm->TimeoutEvt = false;
2209 sm->alt_snonce_valid = false;
Sunil Ravia04bd252022-05-02 22:54:18 -07002210 sm->ptkstart_without_success++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002211
2212 sm->TimeoutCtr++;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002213 if (sm->TimeoutCtr > sm->wpa_auth->conf.wpa_pairwise_update_count) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002214 /* No point in sending the EAPOL-Key - we will disconnect
2215 * immediately following this. */
2216 return;
2217 }
2218
2219 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
2220 "sending 1/4 msg of 4-Way Handshake");
2221 /*
Hai Shalomce48b4a2018-09-05 11:41:35 -07002222 * For infrastructure BSS cases, it is better for the AP not to include
2223 * the PMKID KDE in EAPOL-Key msg 1/4 since it could be used to initiate
2224 * offline search for the passphrase/PSK without having to be able to
2225 * capture a 4-way handshake from a STA that has access to the network.
2226 *
2227 * For IBSS cases, addition of PMKID KDE could be considered even with
2228 * WPA2-PSK cases that use multiple PSKs, but only if there is a single
2229 * possible PSK for this STA. However, this should not be done unless
2230 * there is support for using that information on the supplicant side.
2231 * The concern about exposing PMKID unnecessarily in infrastructure BSS
2232 * cases would also apply here, but at least in the IBSS case, this
2233 * would cover a potential real use case.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002234 */
2235 if (sm->wpa == WPA_VERSION_WPA2 &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002236 (wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) ||
2237 (sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE && sm->pmksa) ||
2238 wpa_key_mgmt_sae(sm->wpa_key_mgmt)) &&
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002239 sm->wpa_key_mgmt != WPA_KEY_MGMT_OSEN) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002240 pmkid = buf;
2241 pmkid_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN;
2242 pmkid[0] = WLAN_EID_VENDOR_SPECIFIC;
2243 pmkid[1] = RSN_SELECTOR_LEN + PMKID_LEN;
2244 RSN_SELECTOR_PUT(&pmkid[2], RSN_KEY_DATA_PMKID);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002245 if (sm->pmksa) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002246 wpa_hexdump(MSG_DEBUG,
2247 "RSN: Message 1/4 PMKID from PMKSA entry",
2248 sm->pmksa->pmkid, PMKID_LEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002249 os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN],
2250 sm->pmksa->pmkid, PMKID_LEN);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002251 } else if (wpa_key_mgmt_suite_b(sm->wpa_key_mgmt)) {
2252 /* No KCK available to derive PMKID */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002253 wpa_printf(MSG_DEBUG,
2254 "RSN: No KCK available to derive PMKID for message 1/4");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002255 pmkid = NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -07002256#ifdef CONFIG_FILS
2257 } else if (wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
2258 if (sm->pmkid_set) {
2259 wpa_hexdump(MSG_DEBUG,
2260 "RSN: Message 1/4 PMKID from FILS/ERP",
2261 sm->pmkid, PMKID_LEN);
2262 os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN],
2263 sm->pmkid, PMKID_LEN);
2264 } else {
2265 /* No PMKID available */
2266 wpa_printf(MSG_DEBUG,
2267 "RSN: No FILS/ERP PMKID available for message 1/4");
2268 pmkid = NULL;
2269 }
2270#endif /* CONFIG_FILS */
2271#ifdef CONFIG_IEEE80211R_AP
2272 } else if (wpa_key_mgmt_ft(sm->wpa_key_mgmt) &&
2273 sm->ft_completed) {
2274 wpa_printf(MSG_DEBUG,
2275 "FT: No PMKID in message 1/4 when using FT protocol");
2276 pmkid = NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -07002277#endif /* CONFIG_IEEE80211R_AP */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002278#ifdef CONFIG_SAE
2279 } else if (wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
2280 if (sm->pmkid_set) {
2281 wpa_hexdump(MSG_DEBUG,
2282 "RSN: Message 1/4 PMKID from SAE",
2283 sm->pmkid, PMKID_LEN);
2284 os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN],
2285 sm->pmkid, PMKID_LEN);
2286 } else {
2287 /* No PMKID available */
2288 wpa_printf(MSG_DEBUG,
2289 "RSN: No SAE PMKID available for message 1/4");
2290 pmkid = NULL;
2291 }
2292#endif /* CONFIG_SAE */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002293 } else {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002294 /*
2295 * Calculate PMKID since no PMKSA cache entry was
2296 * available with pre-calculated PMKID.
2297 */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002298 rsn_pmkid(sm->PMK, sm->pmk_len, sm->wpa_auth->addr,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002299 sm->addr, &pmkid[2 + RSN_SELECTOR_LEN],
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002300 sm->wpa_key_mgmt);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002301 wpa_hexdump(MSG_DEBUG,
2302 "RSN: Message 1/4 PMKID derived from PMK",
2303 &pmkid[2 + RSN_SELECTOR_LEN], PMKID_LEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002304 }
2305 }
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002306 if (!pmkid)
2307 pmkid_len = 0;
Sunil8cd6f4d2022-06-28 18:40:46 +00002308 key_info = WPA_KEY_INFO_ACK | WPA_KEY_INFO_KEY_TYPE;
2309 if (sm->pairwise_set && sm->wpa != WPA_VERSION_WPA)
2310 key_info |= WPA_KEY_INFO_SECURE;
2311 wpa_send_eapol(sm->wpa_auth, sm, key_info, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002312 sm->ANonce, pmkid, pmkid_len, 0, 0);
2313}
2314
2315
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002316static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002317 const u8 *pmk, unsigned int pmk_len,
Hai Shalomfdcde762020-04-02 11:19:20 -07002318 struct wpa_ptk *ptk, int force_sha256)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002319{
Hai Shalom021b0b52019-04-10 11:17:58 -07002320 const u8 *z = NULL;
Hai Shalom60840252021-02-19 19:02:11 -08002321 size_t z_len = 0, kdk_len;
Hai Shalomfdcde762020-04-02 11:19:20 -07002322 int akmp;
Hai Shalom021b0b52019-04-10 11:17:58 -07002323
Hai Shalom60840252021-02-19 19:02:11 -08002324 if (sm->wpa_auth->conf.force_kdk_derivation ||
2325 (sm->wpa_auth->conf.secure_ltf &&
Hai Shaloma20dcd72022-02-04 13:43:00 -08002326 ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
Hai Shalom60840252021-02-19 19:02:11 -08002327 kdk_len = WPA_KDK_MAX_LEN;
2328 else
2329 kdk_len = 0;
2330
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002331#ifdef CONFIG_IEEE80211R_AP
Hai Shalom81f62d82019-07-22 12:10:00 -07002332 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
2333 if (sm->ft_completed) {
2334 u8 ptk_name[WPA_PMK_NAME_LEN];
2335
2336 return wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->pmk_r1_len,
2337 sm->SNonce, sm->ANonce,
2338 sm->addr, sm->wpa_auth->addr,
2339 sm->pmk_r1_name,
2340 ptk, ptk_name,
2341 sm->wpa_key_mgmt,
Hai Shalom60840252021-02-19 19:02:11 -08002342 sm->pairwise,
2343 kdk_len);
Hai Shalom81f62d82019-07-22 12:10:00 -07002344 }
2345 return wpa_auth_derive_ptk_ft(sm, ptk);
2346 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002347#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002348
Hai Shalom021b0b52019-04-10 11:17:58 -07002349#ifdef CONFIG_DPP2
2350 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP && sm->dpp_z) {
2351 z = wpabuf_head(sm->dpp_z);
2352 z_len = wpabuf_len(sm->dpp_z);
2353 }
2354#endif /* CONFIG_DPP2 */
2355
Hai Shalomfdcde762020-04-02 11:19:20 -07002356 akmp = sm->wpa_key_mgmt;
2357 if (force_sha256)
2358 akmp |= WPA_KEY_MGMT_PSK_SHA256;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002359 return wpa_pmk_to_ptk(pmk, pmk_len, "Pairwise key expansion",
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002360 sm->wpa_auth->addr, sm->addr, sm->ANonce, snonce,
Hai Shalom60840252021-02-19 19:02:11 -08002361 ptk, akmp, sm->pairwise, z, z_len, kdk_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002362}
2363
2364
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002365#ifdef CONFIG_FILS
2366
2367int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002368 size_t pmk_len, const u8 *snonce, const u8 *anonce,
2369 const u8 *dhss, size_t dhss_len,
2370 struct wpabuf *g_sta, struct wpabuf *g_ap)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002371{
2372 u8 ick[FILS_ICK_MAX_LEN];
2373 size_t ick_len;
2374 int res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002375 u8 fils_ft[FILS_FT_MAX_LEN];
Hai Shalom60840252021-02-19 19:02:11 -08002376 size_t fils_ft_len = 0, kdk_len;
2377
2378 if (sm->wpa_auth->conf.force_kdk_derivation ||
2379 (sm->wpa_auth->conf.secure_ltf &&
Hai Shaloma20dcd72022-02-04 13:43:00 -08002380 ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
Hai Shalom60840252021-02-19 19:02:11 -08002381 kdk_len = WPA_KDK_MAX_LEN;
2382 else
2383 kdk_len = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002384
2385 res = fils_pmk_to_ptk(pmk, pmk_len, sm->addr, sm->wpa_auth->addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002386 snonce, anonce, dhss, dhss_len,
2387 &sm->PTK, ick, &ick_len,
2388 sm->wpa_key_mgmt, sm->pairwise,
Hai Shalom60840252021-02-19 19:02:11 -08002389 fils_ft, &fils_ft_len, kdk_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002390 if (res < 0)
2391 return res;
Hai Shalome21d4e82020-04-29 16:34:06 -07002392 sm->PTK_valid = true;
2393 sm->tk_already_set = false;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002394
2395#ifdef CONFIG_IEEE80211R_AP
2396 if (fils_ft_len) {
2397 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
2398 struct wpa_auth_config *conf = &wpa_auth->conf;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002399 u8 pmk_r0[PMK_LEN_MAX], pmk_r0_name[WPA_PMK_NAME_LEN];
2400 int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002401
2402 if (wpa_derive_pmk_r0(fils_ft, fils_ft_len,
2403 conf->ssid, conf->ssid_len,
2404 conf->mobility_domain,
2405 conf->r0_key_holder,
2406 conf->r0_key_holder_len,
Roshan Pius3a1667e2018-07-03 15:17:14 -07002407 sm->addr, pmk_r0, pmk_r0_name,
2408 use_sha384) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002409 return -1;
2410
Roshan Pius3a1667e2018-07-03 15:17:14 -07002411 wpa_ft_store_pmk_fils(sm, pmk_r0, pmk_r0_name);
Hai Shalom81f62d82019-07-22 12:10:00 -07002412 forced_memzero(fils_ft, sizeof(fils_ft));
Hai Shalom021b0b52019-04-10 11:17:58 -07002413
2414 res = wpa_derive_pmk_r1_name(pmk_r0_name, conf->r1_key_holder,
2415 sm->addr, sm->pmk_r1_name,
2416 use_sha384);
Hai Shalom81f62d82019-07-22 12:10:00 -07002417 forced_memzero(pmk_r0, PMK_LEN_MAX);
Hai Shalom021b0b52019-04-10 11:17:58 -07002418 if (res < 0)
2419 return -1;
2420 wpa_hexdump(MSG_DEBUG, "FILS+FT: PMKR1Name", sm->pmk_r1_name,
2421 WPA_PMK_NAME_LEN);
2422 sm->pmk_r1_name_valid = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002423 }
2424#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002425
2426 res = fils_key_auth_sk(ick, ick_len, snonce, anonce,
2427 sm->addr, sm->wpa_auth->addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002428 g_sta ? wpabuf_head(g_sta) : NULL,
2429 g_sta ? wpabuf_len(g_sta) : 0,
2430 g_ap ? wpabuf_head(g_ap) : NULL,
2431 g_ap ? wpabuf_len(g_ap) : 0,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002432 sm->wpa_key_mgmt, sm->fils_key_auth_sta,
2433 sm->fils_key_auth_ap,
2434 &sm->fils_key_auth_len);
Hai Shalom81f62d82019-07-22 12:10:00 -07002435 forced_memzero(ick, sizeof(ick));
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002436
2437 /* Store nonces for (Re)Association Request/Response frame processing */
2438 os_memcpy(sm->SNonce, snonce, FILS_NONCE_LEN);
2439 os_memcpy(sm->ANonce, anonce, FILS_NONCE_LEN);
2440
2441 return res;
2442}
2443
2444
2445static int wpa_aead_decrypt(struct wpa_state_machine *sm, struct wpa_ptk *ptk,
2446 u8 *buf, size_t buf_len, u16 *_key_data_len)
2447{
2448 struct ieee802_1x_hdr *hdr;
2449 struct wpa_eapol_key *key;
2450 u8 *pos;
2451 u16 key_data_len;
2452 u8 *tmp;
2453 const u8 *aad[1];
2454 size_t aad_len[1];
2455
2456 hdr = (struct ieee802_1x_hdr *) buf;
2457 key = (struct wpa_eapol_key *) (hdr + 1);
2458 pos = (u8 *) (key + 1);
2459 key_data_len = WPA_GET_BE16(pos);
2460 if (key_data_len < AES_BLOCK_SIZE ||
2461 key_data_len > buf_len - sizeof(*hdr) - sizeof(*key) - 2) {
2462 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO,
2463 "No room for AES-SIV data in the frame");
2464 return -1;
2465 }
2466 pos += 2; /* Pointing at the Encrypted Key Data field */
2467
2468 tmp = os_malloc(key_data_len);
2469 if (!tmp)
2470 return -1;
2471
2472 /* AES-SIV AAD from EAPOL protocol version field (inclusive) to
2473 * to Key Data (exclusive). */
2474 aad[0] = buf;
2475 aad_len[0] = pos - buf;
2476 if (aes_siv_decrypt(ptk->kek, ptk->kek_len, pos, key_data_len,
2477 1, aad, aad_len, tmp) < 0) {
2478 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO,
2479 "Invalid AES-SIV data in the frame");
2480 bin_clear_free(tmp, key_data_len);
2481 return -1;
2482 }
2483
2484 /* AEAD decryption and validation completed successfully */
2485 key_data_len -= AES_BLOCK_SIZE;
2486 wpa_hexdump_key(MSG_DEBUG, "WPA: Decrypted Key Data",
2487 tmp, key_data_len);
2488
2489 /* Replace Key Data field with the decrypted version */
2490 os_memcpy(pos, tmp, key_data_len);
2491 pos -= 2; /* Key Data Length field */
2492 WPA_PUT_BE16(pos, key_data_len);
2493 bin_clear_free(tmp, key_data_len);
2494 if (_key_data_len)
2495 *_key_data_len = key_data_len;
2496 return 0;
2497}
2498
2499
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002500const u8 * wpa_fils_validate_fils_session(struct wpa_state_machine *sm,
2501 const u8 *ies, size_t ies_len,
2502 const u8 *fils_session)
2503{
2504 const u8 *ie, *end;
2505 const u8 *session = NULL;
2506
2507 if (!wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
2508 wpa_printf(MSG_DEBUG,
2509 "FILS: Not a FILS AKM - reject association");
2510 return NULL;
2511 }
2512
2513 /* Verify Session element */
2514 ie = ies;
2515 end = ((const u8 *) ie) + ies_len;
2516 while (ie + 1 < end) {
2517 if (ie + 2 + ie[1] > end)
2518 break;
2519 if (ie[0] == WLAN_EID_EXTENSION &&
2520 ie[1] >= 1 + FILS_SESSION_LEN &&
2521 ie[2] == WLAN_EID_EXT_FILS_SESSION) {
2522 session = ie;
2523 break;
2524 }
2525 ie += 2 + ie[1];
2526 }
2527
2528 if (!session) {
2529 wpa_printf(MSG_DEBUG,
2530 "FILS: %s: Could not find FILS Session element in Assoc Req - reject",
2531 __func__);
2532 return NULL;
2533 }
2534
2535 if (!fils_session) {
2536 wpa_printf(MSG_DEBUG,
2537 "FILS: %s: Could not find FILS Session element in STA entry - reject",
2538 __func__);
2539 return NULL;
2540 }
2541
2542 if (os_memcmp(fils_session, session + 3, FILS_SESSION_LEN) != 0) {
2543 wpa_printf(MSG_DEBUG, "FILS: Session mismatch");
2544 wpa_hexdump(MSG_DEBUG, "FILS: Expected FILS Session",
2545 fils_session, FILS_SESSION_LEN);
2546 wpa_hexdump(MSG_DEBUG, "FILS: Received FILS Session",
2547 session + 3, FILS_SESSION_LEN);
2548 return NULL;
2549 }
2550 return session;
2551}
2552
2553
2554int wpa_fils_validate_key_confirm(struct wpa_state_machine *sm, const u8 *ies,
2555 size_t ies_len)
2556{
2557 struct ieee802_11_elems elems;
2558
2559 if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed) {
2560 wpa_printf(MSG_DEBUG,
2561 "FILS: Failed to parse decrypted elements");
2562 return -1;
2563 }
2564
2565 if (!elems.fils_session) {
2566 wpa_printf(MSG_DEBUG, "FILS: No FILS Session element");
2567 return -1;
2568 }
2569
2570 if (!elems.fils_key_confirm) {
2571 wpa_printf(MSG_DEBUG, "FILS: No FILS Key Confirm element");
2572 return -1;
2573 }
2574
2575 if (elems.fils_key_confirm_len != sm->fils_key_auth_len) {
2576 wpa_printf(MSG_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07002577 "FILS: Unexpected Key-Auth length %d (expected %zu)",
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002578 elems.fils_key_confirm_len,
Hai Shalomfdcde762020-04-02 11:19:20 -07002579 sm->fils_key_auth_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002580 return -1;
2581 }
2582
2583 if (os_memcmp(elems.fils_key_confirm, sm->fils_key_auth_sta,
2584 sm->fils_key_auth_len) != 0) {
2585 wpa_printf(MSG_DEBUG, "FILS: Key-Auth mismatch");
2586 wpa_hexdump(MSG_DEBUG, "FILS: Received Key-Auth",
2587 elems.fils_key_confirm, elems.fils_key_confirm_len);
2588 wpa_hexdump(MSG_DEBUG, "FILS: Expected Key-Auth",
2589 sm->fils_key_auth_sta, sm->fils_key_auth_len);
2590 return -1;
2591 }
2592
2593 return 0;
2594}
2595
2596
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002597int fils_decrypt_assoc(struct wpa_state_machine *sm, const u8 *fils_session,
2598 const struct ieee80211_mgmt *mgmt, size_t frame_len,
2599 u8 *pos, size_t left)
2600{
2601 u16 fc, stype;
2602 const u8 *end, *ie_start, *ie, *session, *crypt;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002603 const u8 *aad[5];
2604 size_t aad_len[5];
2605
2606 if (!sm || !sm->PTK_valid) {
2607 wpa_printf(MSG_DEBUG,
2608 "FILS: No KEK to decrypt Assocication Request frame");
2609 return -1;
2610 }
2611
2612 if (!wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
2613 wpa_printf(MSG_DEBUG,
2614 "FILS: Not a FILS AKM - reject association");
2615 return -1;
2616 }
2617
2618 end = ((const u8 *) mgmt) + frame_len;
2619 fc = le_to_host16(mgmt->frame_control);
2620 stype = WLAN_FC_GET_STYPE(fc);
2621 if (stype == WLAN_FC_STYPE_REASSOC_REQ)
2622 ie_start = mgmt->u.reassoc_req.variable;
2623 else
2624 ie_start = mgmt->u.assoc_req.variable;
2625 ie = ie_start;
2626
2627 /*
2628 * Find FILS Session element which is the last unencrypted element in
2629 * the frame.
2630 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002631 session = wpa_fils_validate_fils_session(sm, ie, end - ie,
2632 fils_session);
2633 if (!session) {
2634 wpa_printf(MSG_DEBUG, "FILS: Session validation failed");
2635 return -1;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002636 }
2637
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002638 crypt = session + 2 + session[1];
2639
2640 if (end - crypt < AES_BLOCK_SIZE) {
2641 wpa_printf(MSG_DEBUG,
2642 "FILS: Too short frame to include AES-SIV data");
2643 return -1;
2644 }
2645
2646 /* AES-SIV AAD vectors */
2647
2648 /* The STA's MAC address */
2649 aad[0] = mgmt->sa;
2650 aad_len[0] = ETH_ALEN;
2651 /* The AP's BSSID */
2652 aad[1] = mgmt->da;
2653 aad_len[1] = ETH_ALEN;
2654 /* The STA's nonce */
2655 aad[2] = sm->SNonce;
2656 aad_len[2] = FILS_NONCE_LEN;
2657 /* The AP's nonce */
2658 aad[3] = sm->ANonce;
2659 aad_len[3] = FILS_NONCE_LEN;
2660 /*
2661 * The (Re)Association Request frame from the Capability Information
2662 * field to the FILS Session element (both inclusive).
2663 */
2664 aad[4] = (const u8 *) &mgmt->u.assoc_req.capab_info;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002665 aad_len[4] = crypt - aad[4];
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002666
2667 if (aes_siv_decrypt(sm->PTK.kek, sm->PTK.kek_len, crypt, end - crypt,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002668 5, aad, aad_len, pos + (crypt - ie_start)) < 0) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002669 wpa_printf(MSG_DEBUG,
2670 "FILS: Invalid AES-SIV data in the frame");
2671 return -1;
2672 }
2673 wpa_hexdump(MSG_DEBUG, "FILS: Decrypted Association Request elements",
2674 pos, left - AES_BLOCK_SIZE);
2675
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002676 if (wpa_fils_validate_key_confirm(sm, pos, left - AES_BLOCK_SIZE) < 0) {
2677 wpa_printf(MSG_DEBUG, "FILS: Key Confirm validation failed");
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002678 return -1;
2679 }
2680
2681 return left - AES_BLOCK_SIZE;
2682}
2683
2684
2685int fils_encrypt_assoc(struct wpa_state_machine *sm, u8 *buf,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002686 size_t current_len, size_t max_len,
2687 const struct wpabuf *hlp)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002688{
2689 u8 *end = buf + max_len;
2690 u8 *pos = buf + current_len;
2691 struct ieee80211_mgmt *mgmt;
2692 struct wpabuf *plain;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002693 const u8 *aad[5];
2694 size_t aad_len[5];
2695
2696 if (!sm || !sm->PTK_valid)
2697 return -1;
2698
2699 wpa_hexdump(MSG_DEBUG,
2700 "FILS: Association Response frame before FILS processing",
2701 buf, current_len);
2702
2703 mgmt = (struct ieee80211_mgmt *) buf;
2704
2705 /* AES-SIV AAD vectors */
2706
2707 /* The AP's BSSID */
2708 aad[0] = mgmt->sa;
2709 aad_len[0] = ETH_ALEN;
2710 /* The STA's MAC address */
2711 aad[1] = mgmt->da;
2712 aad_len[1] = ETH_ALEN;
2713 /* The AP's nonce */
2714 aad[2] = sm->ANonce;
2715 aad_len[2] = FILS_NONCE_LEN;
2716 /* The STA's nonce */
2717 aad[3] = sm->SNonce;
2718 aad_len[3] = FILS_NONCE_LEN;
2719 /*
2720 * The (Re)Association Response frame from the Capability Information
2721 * field (the same offset in both Association and Reassociation
2722 * Response frames) to the FILS Session element (both inclusive).
2723 */
2724 aad[4] = (const u8 *) &mgmt->u.assoc_resp.capab_info;
2725 aad_len[4] = pos - aad[4];
2726
2727 /* The following elements will be encrypted with AES-SIV */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002728 plain = fils_prepare_plainbuf(sm, hlp);
2729 if (!plain) {
2730 wpa_printf(MSG_DEBUG, "FILS: Plain buffer prep failed");
2731 return -1;
2732 }
2733
2734 if (pos + wpabuf_len(plain) + AES_BLOCK_SIZE > end) {
2735 wpa_printf(MSG_DEBUG,
2736 "FILS: Not enough room for FILS elements");
Hai Shalom81f62d82019-07-22 12:10:00 -07002737 wpabuf_clear_free(plain);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002738 return -1;
2739 }
2740
2741 wpa_hexdump_buf_key(MSG_DEBUG, "FILS: Association Response plaintext",
2742 plain);
2743
2744 if (aes_siv_encrypt(sm->PTK.kek, sm->PTK.kek_len,
2745 wpabuf_head(plain), wpabuf_len(plain),
2746 5, aad, aad_len, pos) < 0) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002747 wpabuf_clear_free(plain);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002748 return -1;
2749 }
2750
2751 wpa_hexdump(MSG_DEBUG,
2752 "FILS: Encrypted Association Response elements",
2753 pos, AES_BLOCK_SIZE + wpabuf_len(plain));
2754 current_len += wpabuf_len(plain) + AES_BLOCK_SIZE;
Hai Shalom81f62d82019-07-22 12:10:00 -07002755 wpabuf_clear_free(plain);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002756
2757 sm->fils_completed = 1;
2758
2759 return current_len;
2760}
2761
2762
2763static struct wpabuf * fils_prepare_plainbuf(struct wpa_state_machine *sm,
2764 const struct wpabuf *hlp)
2765{
2766 struct wpabuf *plain;
2767 u8 *len, *tmp, *tmp2;
2768 u8 hdr[2];
Hai Shaloma20dcd72022-02-04 13:43:00 -08002769 u8 *gtk, stub_gtk[32];
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002770 size_t gtk_len;
2771 struct wpa_group *gsm;
Hai Shalomfdcde762020-04-02 11:19:20 -07002772 size_t plain_len;
2773 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002774
Hai Shalomfdcde762020-04-02 11:19:20 -07002775 plain_len = 1000 + ieee80211w_kde_len(sm);
2776 if (conf->transition_disable)
2777 plain_len += 2 + RSN_SELECTOR_LEN + 1;
2778 plain = wpabuf_alloc(plain_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002779 if (!plain)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002780 return NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002781
2782 /* TODO: FILS Public Key */
2783
2784 /* FILS Key Confirmation */
2785 wpabuf_put_u8(plain, WLAN_EID_EXTENSION); /* Element ID */
2786 wpabuf_put_u8(plain, 1 + sm->fils_key_auth_len); /* Length */
2787 /* Element ID Extension */
2788 wpabuf_put_u8(plain, WLAN_EID_EXT_FILS_KEY_CONFIRM);
2789 wpabuf_put_data(plain, sm->fils_key_auth_ap, sm->fils_key_auth_len);
2790
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002791 /* FILS HLP Container */
2792 if (hlp)
2793 wpabuf_put_buf(plain, hlp);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002794
2795 /* TODO: FILS IP Address Assignment */
2796
2797 /* Key Delivery */
2798 gsm = sm->group;
2799 wpabuf_put_u8(plain, WLAN_EID_EXTENSION); /* Element ID */
2800 len = wpabuf_put(plain, 1);
2801 wpabuf_put_u8(plain, WLAN_EID_EXT_KEY_DELIVERY);
2802 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN,
2803 wpabuf_put(plain, WPA_KEY_RSC_LEN));
2804 /* GTK KDE */
2805 gtk = gsm->GTK[gsm->GN - 1];
2806 gtk_len = gsm->GTK_len;
Hai Shalomfdcde762020-04-02 11:19:20 -07002807 if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002808 /*
2809 * Provide unique random GTK to each STA to prevent use
2810 * of GTK in the BSS.
2811 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08002812 if (random_get_bytes(stub_gtk, gtk_len) < 0) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002813 wpabuf_clear_free(plain);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002814 return NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002815 }
Hai Shaloma20dcd72022-02-04 13:43:00 -08002816 gtk = stub_gtk;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002817 }
2818 hdr[0] = gsm->GN & 0x03;
2819 hdr[1] = 0;
2820 tmp = wpabuf_put(plain, 0);
2821 tmp2 = wpa_add_kde(tmp, RSN_KEY_DATA_GROUPKEY, hdr, 2,
2822 gtk, gtk_len);
2823 wpabuf_put(plain, tmp2 - tmp);
2824
Hai Shalomfdcde762020-04-02 11:19:20 -07002825 /* IGTK KDE and BIGTK KDE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002826 tmp = wpabuf_put(plain, 0);
2827 tmp2 = ieee80211w_kde_add(sm, tmp);
2828 wpabuf_put(plain, tmp2 - tmp);
2829
Hai Shalomfdcde762020-04-02 11:19:20 -07002830 if (conf->transition_disable) {
2831 tmp = wpabuf_put(plain, 0);
2832 tmp2 = wpa_add_kde(tmp, WFA_KEY_DATA_TRANSITION_DISABLE,
2833 &conf->transition_disable, 1, NULL, 0);
2834 wpabuf_put(plain, tmp2 - tmp);
2835 }
2836
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002837 *len = (u8 *) wpabuf_put(plain, 0) - len - 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08002838
2839#ifdef CONFIG_OCV
2840 if (wpa_auth_uses_ocv(sm)) {
2841 struct wpa_channel_info ci;
2842 u8 *pos;
2843
2844 if (wpa_channel_info(sm->wpa_auth, &ci) != 0) {
2845 wpa_printf(MSG_WARNING,
2846 "FILS: Failed to get channel info for OCI element");
Hai Shalom81f62d82019-07-22 12:10:00 -07002847 wpabuf_clear_free(plain);
Hai Shalom74f70d42019-02-11 14:42:39 -08002848 return NULL;
2849 }
Hai Shalom899fcc72020-10-19 14:38:18 -07002850#ifdef CONFIG_TESTING_OPTIONS
2851 if (conf->oci_freq_override_fils_assoc) {
2852 wpa_printf(MSG_INFO,
2853 "TEST: Override OCI frequency %d -> %u MHz",
2854 ci.frequency,
2855 conf->oci_freq_override_fils_assoc);
2856 ci.frequency = conf->oci_freq_override_fils_assoc;
2857 }
2858#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom74f70d42019-02-11 14:42:39 -08002859
2860 pos = wpabuf_put(plain, OCV_OCI_EXTENDED_LEN);
2861 if (ocv_insert_extended_oci(&ci, pos) < 0) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002862 wpabuf_clear_free(plain);
Hai Shalom74f70d42019-02-11 14:42:39 -08002863 return NULL;
2864 }
2865 }
2866#endif /* CONFIG_OCV */
2867
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002868 return plain;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002869}
2870
2871
2872int fils_set_tk(struct wpa_state_machine *sm)
2873{
2874 enum wpa_alg alg;
2875 int klen;
2876
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002877 if (!sm || !sm->PTK_valid) {
2878 wpa_printf(MSG_DEBUG, "FILS: No valid PTK available to set TK");
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002879 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002880 }
2881 if (sm->tk_already_set) {
2882 wpa_printf(MSG_DEBUG, "FILS: TK already set to the driver");
2883 return -1;
2884 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002885
2886 alg = wpa_cipher_to_alg(sm->pairwise);
2887 klen = wpa_cipher_key_len(sm->pairwise);
2888
2889 wpa_printf(MSG_DEBUG, "FILS: Configure TK to the driver");
2890 if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0,
Hai Shalomfdcde762020-04-02 11:19:20 -07002891 sm->PTK.tk, klen, KEY_FLAG_PAIRWISE_RX_TX)) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002892 wpa_printf(MSG_DEBUG, "FILS: Failed to set TK to the driver");
2893 return -1;
2894 }
Sunil8cd6f4d2022-06-28 18:40:46 +00002895 sm->pairwise_set = true;
Hai Shalome21d4e82020-04-29 16:34:06 -07002896 sm->tk_already_set = true;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002897
Hai Shalom60840252021-02-19 19:02:11 -08002898 wpa_auth_store_ptksa(sm->wpa_auth, sm->addr, sm->pairwise,
2899 dot11RSNAConfigPMKLifetime, &sm->PTK);
2900
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002901 return 0;
2902}
2903
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002904
2905u8 * hostapd_eid_assoc_fils_session(struct wpa_state_machine *sm, u8 *buf,
2906 const u8 *fils_session, struct wpabuf *hlp)
2907{
2908 struct wpabuf *plain;
2909 u8 *pos = buf;
2910
2911 /* FILS Session */
2912 *pos++ = WLAN_EID_EXTENSION; /* Element ID */
2913 *pos++ = 1 + FILS_SESSION_LEN; /* Length */
2914 *pos++ = WLAN_EID_EXT_FILS_SESSION; /* Element ID Extension */
2915 os_memcpy(pos, fils_session, FILS_SESSION_LEN);
2916 pos += FILS_SESSION_LEN;
2917
2918 plain = fils_prepare_plainbuf(sm, hlp);
2919 if (!plain) {
2920 wpa_printf(MSG_DEBUG, "FILS: Plain buffer prep failed");
2921 return NULL;
2922 }
2923
2924 os_memcpy(pos, wpabuf_head(plain), wpabuf_len(plain));
2925 pos += wpabuf_len(plain);
2926
Hai Shalomfdcde762020-04-02 11:19:20 -07002927 wpa_printf(MSG_DEBUG, "%s: plain buf_len: %zu", __func__,
2928 wpabuf_len(plain));
Hai Shalom81f62d82019-07-22 12:10:00 -07002929 wpabuf_clear_free(plain);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002930 sm->fils_completed = 1;
2931 return pos;
2932}
2933
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002934#endif /* CONFIG_FILS */
2935
2936
Hai Shalom74f70d42019-02-11 14:42:39 -08002937#ifdef CONFIG_OCV
2938int get_sta_tx_parameters(struct wpa_state_machine *sm, int ap_max_chanwidth,
2939 int ap_seg1_idx, int *bandwidth, int *seg1_idx)
2940{
2941 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
2942
2943 if (!wpa_auth->cb->get_sta_tx_params)
2944 return -1;
2945 return wpa_auth->cb->get_sta_tx_params(wpa_auth->cb_ctx, sm->addr,
2946 ap_max_chanwidth, ap_seg1_idx,
2947 bandwidth, seg1_idx);
2948}
2949#endif /* CONFIG_OCV */
2950
2951
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002952SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
2953{
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002954 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002955 struct wpa_ptk PTK;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07002956 int ok = 0, psk_found = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002957 const u8 *pmk = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002958 size_t pmk_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002959 int ft;
2960 const u8 *eapol_key_ie, *key_data, *mic;
2961 u16 key_data_length;
2962 size_t mic_len, eapol_key_ie_len;
2963 struct ieee802_1x_hdr *hdr;
2964 struct wpa_eapol_key *key;
2965 struct wpa_eapol_ie_parse kde;
Hai Shalom021b0b52019-04-10 11:17:58 -07002966 int vlan_id = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002967 int owe_ptk_workaround = !!wpa_auth->conf.owe_ptk_workaround;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002968
2969 SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07002970 sm->EAPOLKeyReceived = false;
2971 sm->update_snonce = false;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002972 os_memset(&PTK, 0, sizeof(PTK));
2973
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002974 mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002975
2976 /* WPA with IEEE 802.1X: use the derived PMK from EAP
2977 * WPA-PSK: iterate through possible PSKs and select the one matching
2978 * the packet */
2979 for (;;) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002980 if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
2981 !wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002982 pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr,
Hai Shalom021b0b52019-04-10 11:17:58 -07002983 sm->p2p_dev_addr, pmk, &pmk_len,
2984 &vlan_id);
Hai Shalomfdcde762020-04-02 11:19:20 -07002985 if (!pmk)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002986 break;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07002987 psk_found = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002988#ifdef CONFIG_IEEE80211R_AP
2989 if (wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) {
2990 os_memcpy(sm->xxkey, pmk, pmk_len);
2991 sm->xxkey_len = pmk_len;
2992 }
2993#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002994 } else {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002995 pmk = sm->PMK;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002996 pmk_len = sm->pmk_len;
2997 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002998
Hai Shalom81f62d82019-07-22 12:10:00 -07002999 if ((!pmk || !pmk_len) && sm->pmksa) {
3000 wpa_printf(MSG_DEBUG, "WPA: Use PMK from PMKSA cache");
3001 pmk = sm->pmksa->pmk;
3002 pmk_len = sm->pmksa->pmk_len;
3003 }
3004
Hai Shalomfdcde762020-04-02 11:19:20 -07003005 if (wpa_derive_ptk(sm, sm->SNonce, pmk, pmk_len, &PTK,
3006 owe_ptk_workaround == 2) < 0)
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003007 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003008
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003009 if (mic_len &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003010 wpa_verify_key_mic(sm->wpa_key_mgmt, pmk_len, &PTK,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003011 sm->last_rx_eapol_key,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003012 sm->last_rx_eapol_key_len) == 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07003013 if (sm->PMK != pmk) {
3014 os_memcpy(sm->PMK, pmk, pmk_len);
3015 sm->pmk_len = pmk_len;
3016 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003017 ok = 1;
3018 break;
3019 }
3020
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003021#ifdef CONFIG_FILS
3022 if (!mic_len &&
3023 wpa_aead_decrypt(sm, &PTK, sm->last_rx_eapol_key,
3024 sm->last_rx_eapol_key_len, NULL) == 0) {
3025 ok = 1;
3026 break;
3027 }
3028#endif /* CONFIG_FILS */
3029
Hai Shalomfdcde762020-04-02 11:19:20 -07003030#ifdef CONFIG_OWE
3031 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE && pmk_len > 32 &&
3032 owe_ptk_workaround == 1) {
3033 wpa_printf(MSG_DEBUG,
3034 "OWE: Try PTK derivation workaround with SHA256");
3035 owe_ptk_workaround = 2;
3036 continue;
3037 }
3038#endif /* CONFIG_OWE */
3039
Roshan Pius3a1667e2018-07-03 15:17:14 -07003040 if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
3041 wpa_key_mgmt_sae(sm->wpa_key_mgmt))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003042 break;
3043 }
3044
Sunil Ravia04bd252022-05-02 22:54:18 -07003045 if (!ok && wpa_key_mgmt_wpa_psk_no_sae(sm->wpa_key_mgmt) &&
3046 wpa_auth->conf.radius_psk && wpa_auth->cb->request_radius_psk &&
3047 !sm->waiting_radius_psk) {
3048 wpa_printf(MSG_DEBUG, "No PSK available - ask RADIUS server");
3049 wpa_auth->cb->request_radius_psk(wpa_auth->cb_ctx, sm->addr,
3050 sm->wpa_key_mgmt,
3051 sm->ANonce,
3052 sm->last_rx_eapol_key,
3053 sm->last_rx_eapol_key_len);
3054 sm->waiting_radius_psk = 1;
3055 return;
3056 }
3057
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003058 if (!ok) {
3059 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
3060 "invalid MIC in msg 2/4 of 4-Way Handshake");
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07003061 if (psk_found)
3062 wpa_auth_psk_failure_report(sm->wpa_auth, sm->addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003063 return;
3064 }
3065
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003066 /*
3067 * Note: last_rx_eapol_key length fields have already been validated in
3068 * wpa_receive().
3069 */
3070 hdr = (struct ieee802_1x_hdr *) sm->last_rx_eapol_key;
3071 key = (struct wpa_eapol_key *) (hdr + 1);
3072 mic = (u8 *) (key + 1);
3073 key_data = mic + mic_len + 2;
3074 key_data_length = WPA_GET_BE16(mic + mic_len);
3075 if (key_data_length > sm->last_rx_eapol_key_len - sizeof(*hdr) -
3076 sizeof(*key) - mic_len - 2)
3077 return;
3078
3079 if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) {
3080 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
3081 "received EAPOL-Key msg 2/4 with invalid Key Data contents");
3082 return;
3083 }
3084 if (kde.rsn_ie) {
3085 eapol_key_ie = kde.rsn_ie;
3086 eapol_key_ie_len = kde.rsn_ie_len;
3087 } else if (kde.osen) {
3088 eapol_key_ie = kde.osen;
3089 eapol_key_ie_len = kde.osen_len;
3090 } else {
3091 eapol_key_ie = kde.wpa_ie;
3092 eapol_key_ie_len = kde.wpa_ie_len;
3093 }
3094 ft = sm->wpa == WPA_VERSION_WPA2 && wpa_key_mgmt_ft(sm->wpa_key_mgmt);
Hai Shalomfdcde762020-04-02 11:19:20 -07003095 if (!sm->wpa_ie ||
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003096 wpa_compare_rsn_ie(ft, sm->wpa_ie, sm->wpa_ie_len,
3097 eapol_key_ie, eapol_key_ie_len)) {
3098 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
3099 "WPA IE from (Re)AssocReq did not match with msg 2/4");
3100 if (sm->wpa_ie) {
3101 wpa_hexdump(MSG_DEBUG, "WPA IE in AssocReq",
3102 sm->wpa_ie, sm->wpa_ie_len);
3103 }
3104 wpa_hexdump(MSG_DEBUG, "WPA IE in msg 2/4",
3105 eapol_key_ie, eapol_key_ie_len);
3106 /* MLME-DEAUTHENTICATE.request */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003107 wpa_sta_disconnect(wpa_auth, sm->addr,
3108 WLAN_REASON_PREV_AUTH_NOT_VALID);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003109 return;
3110 }
Hai Shalomc3565922019-10-28 11:58:20 -07003111 if ((!sm->rsnxe && kde.rsnxe) ||
3112 (sm->rsnxe && !kde.rsnxe) ||
3113 (sm->rsnxe && kde.rsnxe &&
3114 (sm->rsnxe_len != kde.rsnxe_len ||
3115 os_memcmp(sm->rsnxe, kde.rsnxe, sm->rsnxe_len) != 0))) {
3116 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
3117 "RSNXE from (Re)AssocReq did not match the one in EAPOL-Key msg 2/4");
3118 wpa_hexdump(MSG_DEBUG, "RSNXE in AssocReq",
3119 sm->rsnxe, sm->rsnxe_len);
3120 wpa_hexdump(MSG_DEBUG, "RSNXE in EAPOL-Key msg 2/4",
3121 kde.rsnxe, kde.rsnxe_len);
3122 /* MLME-DEAUTHENTICATE.request */
3123 wpa_sta_disconnect(wpa_auth, sm->addr,
3124 WLAN_REASON_PREV_AUTH_NOT_VALID);
3125 return;
3126 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003127#ifdef CONFIG_OCV
3128 if (wpa_auth_uses_ocv(sm)) {
3129 struct wpa_channel_info ci;
3130 int tx_chanwidth;
3131 int tx_seg1_idx;
Hai Shalom899fcc72020-10-19 14:38:18 -07003132 enum oci_verify_result res;
Hai Shalom74f70d42019-02-11 14:42:39 -08003133
3134 if (wpa_channel_info(wpa_auth, &ci) != 0) {
3135 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
3136 "Failed to get channel info to validate received OCI in EAPOL-Key 2/4");
3137 return;
3138 }
3139
3140 if (get_sta_tx_parameters(sm,
3141 channel_width_to_int(ci.chanwidth),
3142 ci.seg1_idx, &tx_chanwidth,
3143 &tx_seg1_idx) < 0)
3144 return;
3145
Hai Shalom899fcc72020-10-19 14:38:18 -07003146 res = ocv_verify_tx_params(kde.oci, kde.oci_len, &ci,
3147 tx_chanwidth, tx_seg1_idx);
3148 if (wpa_auth_uses_ocv(sm) == 2 && res == OCI_NOT_FOUND) {
3149 /* Work around misbehaving STAs */
3150 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
3151 "Disable OCV with a STA that does not send OCI");
3152 wpa_auth_set_ocv(sm, 0);
3153 } else if (res != OCI_SUCCESS) {
3154 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
3155 "OCV failed: %s", ocv_errorstr);
3156 if (wpa_auth->conf.msg_ctx)
3157 wpa_msg(wpa_auth->conf.msg_ctx, MSG_INFO,
3158 OCV_FAILURE "addr=" MACSTR
3159 " frame=eapol-key-m2 error=%s",
3160 MAC2STR(sm->addr), ocv_errorstr);
Hai Shalom74f70d42019-02-11 14:42:39 -08003161 return;
3162 }
3163 }
3164#endif /* CONFIG_OCV */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003165#ifdef CONFIG_IEEE80211R_AP
3166 if (ft && ft_check_msg_2_of_4(wpa_auth, sm, &kde) < 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003167 wpa_sta_disconnect(wpa_auth, sm->addr,
3168 WLAN_REASON_PREV_AUTH_NOT_VALID);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003169 return;
3170 }
3171#endif /* CONFIG_IEEE80211R_AP */
3172#ifdef CONFIG_P2P
3173 if (kde.ip_addr_req && kde.ip_addr_req[0] &&
3174 wpa_auth->ip_pool && WPA_GET_BE32(sm->ip_addr) == 0) {
3175 int idx;
3176 wpa_printf(MSG_DEBUG,
3177 "P2P: IP address requested in EAPOL-Key exchange");
3178 idx = bitfield_get_first_zero(wpa_auth->ip_pool);
3179 if (idx >= 0) {
3180 u32 start = WPA_GET_BE32(wpa_auth->conf.ip_addr_start);
3181 bitfield_set(wpa_auth->ip_pool, idx);
Sunil8cd6f4d2022-06-28 18:40:46 +00003182 sm->ip_addr_bit = idx;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003183 WPA_PUT_BE32(sm->ip_addr, start + idx);
3184 wpa_printf(MSG_DEBUG,
3185 "P2P: Assigned IP address %u.%u.%u.%u to "
Sunil8cd6f4d2022-06-28 18:40:46 +00003186 MACSTR " (bit %u)",
3187 sm->ip_addr[0], sm->ip_addr[1],
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003188 sm->ip_addr[2], sm->ip_addr[3],
Sunil8cd6f4d2022-06-28 18:40:46 +00003189 MAC2STR(sm->addr), sm->ip_addr_bit);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003190 }
3191 }
3192#endif /* CONFIG_P2P */
3193
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003194#ifdef CONFIG_DPP2
3195 if (DPP_VERSION > 1 && kde.dpp_kde) {
3196 wpa_printf(MSG_DEBUG,
3197 "DPP: peer Protocol Version %u Flags 0x%x",
3198 kde.dpp_kde[0], kde.dpp_kde[1]);
3199 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP &&
3200 wpa_auth->conf.dpp_pfs != 2 &&
3201 (kde.dpp_kde[1] & DPP_KDE_PFS_ALLOWED) &&
3202 !sm->dpp_z) {
3203 wpa_printf(MSG_INFO,
3204 "DPP: Peer indicated it supports PFS and local configuration allows this, but PFS was not negotiated for the association");
3205 wpa_sta_disconnect(wpa_auth, sm->addr,
3206 WLAN_REASON_PREV_AUTH_NOT_VALID);
3207 return;
3208 }
3209 }
3210#endif /* CONFIG_DPP2 */
3211
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003212#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003213 if (sm->wpa == WPA_VERSION_WPA2 && wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
3214 /*
3215 * Verify that PMKR1Name from EAPOL-Key message 2/4 matches
3216 * with the value we derived.
3217 */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003218 if (os_memcmp_const(sm->sup_pmk_r1_name, sm->pmk_r1_name,
3219 WPA_PMK_NAME_LEN) != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003220 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07003221 "PMKR1Name mismatch in FT 4-way handshake");
3222 wpa_hexdump(MSG_DEBUG,
3223 "FT: PMKR1Name from Supplicant",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003224 sm->sup_pmk_r1_name, WPA_PMK_NAME_LEN);
3225 wpa_hexdump(MSG_DEBUG, "FT: Derived PMKR1Name",
3226 sm->pmk_r1_name, WPA_PMK_NAME_LEN);
3227 return;
3228 }
3229 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003230#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003231
Hai Shalom021b0b52019-04-10 11:17:58 -07003232 if (vlan_id && wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
3233 wpa_auth_update_vlan(wpa_auth, sm->addr, vlan_id) < 0) {
3234 wpa_sta_disconnect(wpa_auth, sm->addr,
3235 WLAN_REASON_PREV_AUTH_NOT_VALID);
3236 return;
3237 }
3238
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003239 sm->pending_1_of_4_timeout = 0;
3240 eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm);
3241
Hai Shalom60840252021-02-19 19:02:11 -08003242 if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) && sm->PMK != pmk) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003243 /* PSK may have changed from the previous choice, so update
3244 * state machine data based on whatever PSK was selected here.
3245 */
3246 os_memcpy(sm->PMK, pmk, PMK_LEN);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003247 sm->pmk_len = PMK_LEN;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003248 }
3249
Hai Shalome21d4e82020-04-29 16:34:06 -07003250 sm->MICVerified = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003251
3252 os_memcpy(&sm->PTK, &PTK, sizeof(PTK));
Hai Shalom81f62d82019-07-22 12:10:00 -07003253 forced_memzero(&PTK, sizeof(PTK));
Hai Shalome21d4e82020-04-29 16:34:06 -07003254 sm->PTK_valid = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003255}
3256
3257
3258SM_STATE(WPA_PTK, PTKCALCNEGOTIATING2)
3259{
3260 SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING2, wpa_ptk);
3261 sm->TimeoutCtr = 0;
3262}
3263
3264
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003265static int ieee80211w_kde_len(struct wpa_state_machine *sm)
3266{
Hai Shalomfdcde762020-04-02 11:19:20 -07003267 size_t len = 0;
3268
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003269 if (sm->mgmt_frame_prot) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003270 len += 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN;
3271 len += wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
3272 }
3273 if (sm->mgmt_frame_prot && sm->wpa_auth->conf.beacon_prot) {
3274 len += 2 + RSN_SELECTOR_LEN + WPA_BIGTK_KDE_PREFIX_LEN;
3275 len += wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003276 }
3277
Hai Shalomfdcde762020-04-02 11:19:20 -07003278 return len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003279}
3280
3281
3282static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos)
3283{
3284 struct wpa_igtk_kde igtk;
Hai Shalomfdcde762020-04-02 11:19:20 -07003285 struct wpa_bigtk_kde bigtk;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003286 struct wpa_group *gsm = sm->group;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003287 u8 rsc[WPA_KEY_RSC_LEN];
Hai Shalomfdcde762020-04-02 11:19:20 -07003288 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
3289 size_t len = wpa_cipher_key_len(conf->group_mgmt_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003290
3291 if (!sm->mgmt_frame_prot)
3292 return pos;
3293
3294 igtk.keyid[0] = gsm->GN_igtk;
3295 igtk.keyid[1] = 0;
3296 if (gsm->wpa_group_state != WPA_GROUP_SETKEYSDONE ||
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003297 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, rsc) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003298 os_memset(igtk.pn, 0, sizeof(igtk.pn));
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003299 else
3300 os_memcpy(igtk.pn, rsc, sizeof(igtk.pn));
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003301 os_memcpy(igtk.igtk, gsm->IGTK[gsm->GN_igtk - 4], len);
Hai Shalomfdcde762020-04-02 11:19:20 -07003302 if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003303 /*
3304 * Provide unique random IGTK to each STA to prevent use of
3305 * IGTK in the BSS.
3306 */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003307 if (random_get_bytes(igtk.igtk, len) < 0)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003308 return pos;
3309 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003310 pos = wpa_add_kde(pos, RSN_KEY_DATA_IGTK,
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003311 (const u8 *) &igtk, WPA_IGTK_KDE_PREFIX_LEN + len,
3312 NULL, 0);
Sunil Ravia04bd252022-05-02 22:54:18 -07003313 forced_memzero(&igtk, sizeof(igtk));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003314
Hai Shalomfdcde762020-04-02 11:19:20 -07003315 if (!conf->beacon_prot)
3316 return pos;
3317
3318 bigtk.keyid[0] = gsm->GN_bigtk;
3319 bigtk.keyid[1] = 0;
3320 if (gsm->wpa_group_state != WPA_GROUP_SETKEYSDONE ||
3321 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_bigtk, rsc) < 0)
3322 os_memset(bigtk.pn, 0, sizeof(bigtk.pn));
3323 else
3324 os_memcpy(bigtk.pn, rsc, sizeof(bigtk.pn));
3325 os_memcpy(bigtk.bigtk, gsm->BIGTK[gsm->GN_bigtk - 6], len);
Hai Shalom899fcc72020-10-19 14:38:18 -07003326 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
3327 /*
3328 * Provide unique random BIGTK to each OSEN STA to prevent use
3329 * of BIGTK in the BSS.
3330 */
3331 if (random_get_bytes(bigtk.bigtk, len) < 0)
3332 return pos;
3333 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003334 pos = wpa_add_kde(pos, RSN_KEY_DATA_BIGTK,
3335 (const u8 *) &bigtk, WPA_BIGTK_KDE_PREFIX_LEN + len,
3336 NULL, 0);
Sunil Ravia04bd252022-05-02 22:54:18 -07003337 forced_memzero(&bigtk, sizeof(bigtk));
Hai Shalomfdcde762020-04-02 11:19:20 -07003338
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003339 return pos;
3340}
3341
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003342
Hai Shalom74f70d42019-02-11 14:42:39 -08003343static int ocv_oci_len(struct wpa_state_machine *sm)
3344{
3345#ifdef CONFIG_OCV
3346 if (wpa_auth_uses_ocv(sm))
3347 return OCV_OCI_KDE_LEN;
3348#endif /* CONFIG_OCV */
3349 return 0;
3350}
3351
Hai Shalom899fcc72020-10-19 14:38:18 -07003352
3353static int ocv_oci_add(struct wpa_state_machine *sm, u8 **argpos,
3354 unsigned int freq)
Hai Shalom74f70d42019-02-11 14:42:39 -08003355{
3356#ifdef CONFIG_OCV
3357 struct wpa_channel_info ci;
3358
3359 if (!wpa_auth_uses_ocv(sm))
3360 return 0;
3361
3362 if (wpa_channel_info(sm->wpa_auth, &ci) != 0) {
3363 wpa_printf(MSG_WARNING,
3364 "Failed to get channel info for OCI element");
3365 return -1;
3366 }
Hai Shalom899fcc72020-10-19 14:38:18 -07003367#ifdef CONFIG_TESTING_OPTIONS
3368 if (freq) {
3369 wpa_printf(MSG_INFO,
3370 "TEST: Override OCI KDE frequency %d -> %u MHz",
3371 ci.frequency, freq);
3372 ci.frequency = freq;
3373 }
3374#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom74f70d42019-02-11 14:42:39 -08003375
3376 return ocv_insert_oci_kde(&ci, argpos);
3377#else /* CONFIG_OCV */
3378 return 0;
3379#endif /* CONFIG_OCV */
3380}
3381
3382
Hai Shalomfdcde762020-04-02 11:19:20 -07003383#ifdef CONFIG_TESTING_OPTIONS
3384static u8 * replace_ie(const char *name, const u8 *old_buf, size_t *len, u8 eid,
3385 const u8 *ie, size_t ie_len)
3386{
3387 const u8 *elem;
3388 u8 *buf;
3389
3390 wpa_printf(MSG_DEBUG, "TESTING: %s EAPOL override", name);
3391 wpa_hexdump(MSG_DEBUG, "TESTING: wpa_ie before override",
3392 old_buf, *len);
3393 buf = os_malloc(*len + ie_len);
3394 if (!buf)
3395 return NULL;
3396 os_memcpy(buf, old_buf, *len);
3397 elem = get_ie(buf, *len, eid);
3398 if (elem) {
3399 u8 elem_len = 2 + elem[1];
3400
3401 os_memmove((void *) elem, elem + elem_len,
3402 *len - (elem - buf) - elem_len);
3403 *len -= elem_len;
3404 }
3405 os_memcpy(buf + *len, ie, ie_len);
3406 *len += ie_len;
3407 wpa_hexdump(MSG_DEBUG, "TESTING: wpa_ie after EAPOL override",
3408 buf, *len);
3409
3410 return buf;
3411}
3412#endif /* CONFIG_TESTING_OPTIONS */
3413
3414
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003415SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
3416{
Hai Shaloma20dcd72022-02-04 13:43:00 -08003417 u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde = NULL, *pos, stub_gtk[32];
Sunil Ravia04bd252022-05-02 22:54:18 -07003418 size_t gtk_len, kde_len = 0, wpa_ie_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003419 struct wpa_group *gsm = sm->group;
3420 u8 *wpa_ie;
Hai Shalomfdcde762020-04-02 11:19:20 -07003421 int secure, gtkidx, encr = 0;
3422 u8 *wpa_ie_buf = NULL, *wpa_ie_buf2 = NULL;
3423 u8 hdr[2];
3424 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003425
3426 SM_ENTRY_MA(WPA_PTK, PTKINITNEGOTIATING, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07003427 sm->TimeoutEvt = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003428
3429 sm->TimeoutCtr++;
Hai Shalomfdcde762020-04-02 11:19:20 -07003430 if (conf->wpa_disable_eapol_key_retries && sm->TimeoutCtr > 1) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003431 /* Do not allow retransmission of EAPOL-Key msg 3/4 */
3432 return;
3433 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003434 if (sm->TimeoutCtr > conf->wpa_pairwise_update_count) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003435 /* No point in sending the EAPOL-Key - we will disconnect
3436 * immediately following this. */
3437 return;
3438 }
3439
3440 /* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, [MDIE],
Hai Shalomfdcde762020-04-02 11:19:20 -07003441 GTK[GN], IGTK, [BIGTK], [FTIE], [TIE * 2])
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003442 */
3443 os_memset(rsc, 0, WPA_KEY_RSC_LEN);
3444 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc);
3445 /* If FT is used, wpa_auth->wpa_ie includes both RSNIE and MDIE */
3446 wpa_ie = sm->wpa_auth->wpa_ie;
3447 wpa_ie_len = sm->wpa_auth->wpa_ie_len;
Hai Shalomfdcde762020-04-02 11:19:20 -07003448 if (sm->wpa == WPA_VERSION_WPA && (conf->wpa & WPA_PROTO_RSN) &&
3449 wpa_ie_len > wpa_ie[1] + 2U && wpa_ie[0] == WLAN_EID_RSN) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003450 /* WPA-only STA, remove RSN IE and possible MDIE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003451 wpa_ie = wpa_ie + wpa_ie[1] + 2;
Hai Shalom60840252021-02-19 19:02:11 -08003452 if (wpa_ie[0] == WLAN_EID_RSNX)
3453 wpa_ie = wpa_ie + wpa_ie[1] + 2;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003454 if (wpa_ie[0] == WLAN_EID_MOBILITY_DOMAIN)
3455 wpa_ie = wpa_ie + wpa_ie[1] + 2;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003456 wpa_ie_len = wpa_ie[1] + 2;
3457 }
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003458#ifdef CONFIG_TESTING_OPTIONS
Hai Shalomfdcde762020-04-02 11:19:20 -07003459 if (conf->rsne_override_eapol_set) {
3460 wpa_ie_buf2 = replace_ie(
3461 "RSNE", wpa_ie, &wpa_ie_len, WLAN_EID_RSN,
3462 conf->rsne_override_eapol,
3463 conf->rsne_override_eapol_len);
3464 if (!wpa_ie_buf2)
3465 goto done;
3466 wpa_ie = wpa_ie_buf2;
3467 }
3468 if (conf->rsnxe_override_eapol_set) {
3469 wpa_ie_buf = replace_ie(
3470 "RSNXE", wpa_ie, &wpa_ie_len, WLAN_EID_RSNX,
3471 conf->rsnxe_override_eapol,
3472 conf->rsnxe_override_eapol_len);
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003473 if (!wpa_ie_buf)
Hai Shalomfdcde762020-04-02 11:19:20 -07003474 goto done;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003475 wpa_ie = wpa_ie_buf;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003476 }
3477#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003478 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
3479 "sending 3/4 msg of 4-Way Handshake");
3480 if (sm->wpa == WPA_VERSION_WPA2) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003481 if (sm->use_ext_key_id && sm->TimeoutCtr == 1 &&
3482 wpa_auth_set_key(sm->wpa_auth, 0,
3483 wpa_cipher_to_alg(sm->pairwise),
3484 sm->addr,
3485 sm->keyidx_active, sm->PTK.tk,
3486 wpa_cipher_key_len(sm->pairwise),
3487 KEY_FLAG_PAIRWISE_RX)) {
3488 wpa_sta_disconnect(sm->wpa_auth, sm->addr,
3489 WLAN_REASON_PREV_AUTH_NOT_VALID);
3490 return;
3491 }
3492
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003493 /* WPA2 send GTK in the 4-way handshake */
3494 secure = 1;
3495 gtk = gsm->GTK[gsm->GN - 1];
3496 gtk_len = gsm->GTK_len;
Hai Shalomfdcde762020-04-02 11:19:20 -07003497 if (conf->disable_gtk ||
Roshan Pius3a1667e2018-07-03 15:17:14 -07003498 sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003499 /*
3500 * Provide unique random GTK to each STA to prevent use
3501 * of GTK in the BSS.
3502 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003503 if (random_get_bytes(stub_gtk, gtk_len) < 0)
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003504 goto done;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003505 gtk = stub_gtk;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003506 }
Hai Shalomc3565922019-10-28 11:58:20 -07003507 gtkidx = gsm->GN;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003508 _rsc = rsc;
3509 encr = 1;
3510 } else {
3511 /* WPA does not include GTK in msg 3/4 */
3512 secure = 0;
3513 gtk = NULL;
3514 gtk_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003515 _rsc = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003516 if (sm->rx_eapol_key_secure) {
3517 /*
3518 * It looks like Windows 7 supplicant tries to use
3519 * Secure bit in msg 2/4 after having reported Michael
3520 * MIC failure and it then rejects the 4-way handshake
3521 * if msg 3/4 does not set Secure bit. Work around this
3522 * by setting the Secure bit here even in the case of
3523 * WPA if the supplicant used it first.
3524 */
3525 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07003526 "STA used Secure bit in WPA msg 2/4 - set Secure for 3/4 as workaround");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003527 secure = 1;
3528 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003529 }
3530
Hai Shalom74f70d42019-02-11 14:42:39 -08003531 kde_len = wpa_ie_len + ieee80211w_kde_len(sm) + ocv_oci_len(sm);
Hai Shalomfdcde762020-04-02 11:19:20 -07003532
3533 if (sm->use_ext_key_id)
3534 kde_len += 2 + RSN_SELECTOR_LEN + 2;
3535
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003536 if (gtk)
3537 kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003538#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003539 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
3540 kde_len += 2 + PMKID_LEN; /* PMKR1Name into RSN IE */
3541 kde_len += 300; /* FTIE + 2 * TIE */
3542 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003543#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08003544#ifdef CONFIG_P2P
3545 if (WPA_GET_BE32(sm->ip_addr) > 0)
3546 kde_len += 2 + RSN_SELECTOR_LEN + 3 * 4;
3547#endif /* CONFIG_P2P */
Hai Shalomfdcde762020-04-02 11:19:20 -07003548
3549 if (conf->transition_disable)
3550 kde_len += 2 + RSN_SELECTOR_LEN + 1;
3551
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003552#ifdef CONFIG_DPP2
3553 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP)
3554 kde_len += 2 + RSN_SELECTOR_LEN + 2;
3555#endif /* CONFIG_DPP2 */
3556
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003557 kde = os_malloc(kde_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07003558 if (!kde)
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003559 goto done;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003560
3561 pos = kde;
3562 os_memcpy(pos, wpa_ie, wpa_ie_len);
3563 pos += wpa_ie_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003564#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003565 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08003566 int res;
3567 size_t elen;
3568
3569 elen = pos - kde;
3570 res = wpa_insert_pmkid(kde, &elen, sm->pmk_r1_name);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003571 if (res < 0) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003572 wpa_printf(MSG_ERROR,
3573 "FT: Failed to insert PMKR1Name into RSN IE in EAPOL-Key data");
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003574 goto done;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003575 }
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08003576 pos -= wpa_ie_len;
3577 pos += elen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003578 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003579#endif /* CONFIG_IEEE80211R_AP */
Hai Shalomfdcde762020-04-02 11:19:20 -07003580 hdr[1] = 0;
3581
3582 if (sm->use_ext_key_id) {
3583 hdr[0] = sm->keyidx_active & 0x01;
3584 pos = wpa_add_kde(pos, RSN_KEY_DATA_KEYID, hdr, 2, NULL, 0);
3585 }
3586
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003587 if (gtk) {
Hai Shalomc3565922019-10-28 11:58:20 -07003588 hdr[0] = gtkidx & 0x03;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003589 pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
3590 gtk, gtk_len);
3591 }
3592 pos = ieee80211w_kde_add(sm, pos);
Hai Shalom899fcc72020-10-19 14:38:18 -07003593 if (ocv_oci_add(sm, &pos, conf->oci_freq_override_eapol_m3) < 0)
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003594 goto done;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003595
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003596#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003597 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
3598 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003599
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08003600 if (sm->assoc_resp_ftie &&
3601 kde + kde_len - pos >= 2 + sm->assoc_resp_ftie[1]) {
3602 os_memcpy(pos, sm->assoc_resp_ftie,
3603 2 + sm->assoc_resp_ftie[1]);
3604 res = 2 + sm->assoc_resp_ftie[1];
3605 } else {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003606 int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt);
3607
3608 res = wpa_write_ftie(conf, use_sha384,
3609 conf->r0_key_holder,
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08003610 conf->r0_key_holder_len,
3611 NULL, NULL, pos,
3612 kde + kde_len - pos,
Hai Shalomfdcde762020-04-02 11:19:20 -07003613 NULL, 0, 0);
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08003614 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003615 if (res < 0) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003616 wpa_printf(MSG_ERROR,
3617 "FT: Failed to insert FTIE into EAPOL-Key Key Data");
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003618 goto done;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003619 }
3620 pos += res;
3621
3622 /* TIE[ReassociationDeadline] (TU) */
3623 *pos++ = WLAN_EID_TIMEOUT_INTERVAL;
3624 *pos++ = 5;
3625 *pos++ = WLAN_TIMEOUT_REASSOC_DEADLINE;
3626 WPA_PUT_LE32(pos, conf->reassociation_deadline);
3627 pos += 4;
3628
3629 /* TIE[KeyLifetime] (seconds) */
3630 *pos++ = WLAN_EID_TIMEOUT_INTERVAL;
3631 *pos++ = 5;
3632 *pos++ = WLAN_TIMEOUT_KEY_LIFETIME;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003633 WPA_PUT_LE32(pos, conf->r0_key_lifetime);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003634 pos += 4;
3635 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003636#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08003637#ifdef CONFIG_P2P
3638 if (WPA_GET_BE32(sm->ip_addr) > 0) {
3639 u8 addr[3 * 4];
3640 os_memcpy(addr, sm->ip_addr, 4);
Hai Shalomfdcde762020-04-02 11:19:20 -07003641 os_memcpy(addr + 4, conf->ip_addr_mask, 4);
3642 os_memcpy(addr + 8, conf->ip_addr_go, 4);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08003643 pos = wpa_add_kde(pos, WFA_KEY_DATA_IP_ADDR_ALLOC,
3644 addr, sizeof(addr), NULL, 0);
3645 }
3646#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003647
Hai Shalomfdcde762020-04-02 11:19:20 -07003648 if (conf->transition_disable)
3649 pos = wpa_add_kde(pos, WFA_KEY_DATA_TRANSITION_DISABLE,
3650 &conf->transition_disable, 1, NULL, 0);
3651
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003652#ifdef CONFIG_DPP2
3653 if (DPP_VERSION > 1 && sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP) {
3654 u8 payload[2];
3655
3656 payload[0] = DPP_VERSION; /* Protocol Version */
3657 payload[1] = 0; /* Flags */
3658 if (conf->dpp_pfs == 0)
3659 payload[1] |= DPP_KDE_PFS_ALLOWED;
3660 else if (conf->dpp_pfs == 1)
3661 payload[1] |= DPP_KDE_PFS_ALLOWED |
3662 DPP_KDE_PFS_REQUIRED;
3663 pos = wpa_add_kde(pos, WFA_KEY_DATA_DPP,
3664 payload, sizeof(payload), NULL, 0);
3665 }
3666#endif /* CONFIG_DPP2 */
3667
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003668 wpa_send_eapol(sm->wpa_auth, sm,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003669 (secure ? WPA_KEY_INFO_SECURE : 0) |
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003670 (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
3671 WPA_KEY_INFO_MIC : 0) |
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003672 WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL |
3673 WPA_KEY_INFO_KEY_TYPE,
Hai Shalomc3565922019-10-28 11:58:20 -07003674 _rsc, sm->ANonce, kde, pos - kde, 0, encr);
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003675done:
Sunil Ravia04bd252022-05-02 22:54:18 -07003676 bin_clear_free(kde, kde_len);
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003677 os_free(wpa_ie_buf);
Hai Shalomfdcde762020-04-02 11:19:20 -07003678 os_free(wpa_ie_buf2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003679}
3680
3681
3682SM_STATE(WPA_PTK, PTKINITDONE)
3683{
3684 SM_ENTRY_MA(WPA_PTK, PTKINITDONE, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07003685 sm->EAPOLKeyReceived = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003686 if (sm->Pair) {
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07003687 enum wpa_alg alg = wpa_cipher_to_alg(sm->pairwise);
3688 int klen = wpa_cipher_key_len(sm->pairwise);
Hai Shalomfdcde762020-04-02 11:19:20 -07003689 int res;
3690
3691 if (sm->use_ext_key_id)
3692 res = wpa_auth_set_key(sm->wpa_auth, 0, 0, sm->addr,
3693 sm->keyidx_active, NULL, 0,
3694 KEY_FLAG_PAIRWISE_RX_TX_MODIFY);
3695 else
3696 res = wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr,
3697 0, sm->PTK.tk, klen,
3698 KEY_FLAG_PAIRWISE_RX_TX);
3699 if (res) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003700 wpa_sta_disconnect(sm->wpa_auth, sm->addr,
3701 WLAN_REASON_PREV_AUTH_NOT_VALID);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003702 return;
3703 }
3704 /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */
Hai Shalome21d4e82020-04-29 16:34:06 -07003705 sm->pairwise_set = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003706
Hai Shalom81f62d82019-07-22 12:10:00 -07003707 wpa_auth_set_ptk_rekey_timer(sm);
Hai Shalom60840252021-02-19 19:02:11 -08003708 wpa_auth_store_ptksa(sm->wpa_auth, sm->addr, sm->pairwise,
3709 dot11RSNAConfigPMKLifetime, &sm->PTK);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003710
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003711 if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
3712 sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP ||
3713 sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003714 wpa_auth_set_eapol(sm->wpa_auth, sm->addr,
3715 WPA_EAPOL_authorized, 1);
3716 }
3717 }
3718
3719 if (0 /* IBSS == TRUE */) {
3720 sm->keycount++;
3721 if (sm->keycount == 2) {
3722 wpa_auth_set_eapol(sm->wpa_auth, sm->addr,
3723 WPA_EAPOL_portValid, 1);
3724 }
3725 } else {
3726 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid,
3727 1);
3728 }
Hai Shalome21d4e82020-04-29 16:34:06 -07003729 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyAvailable,
3730 false);
3731 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyDone, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003732 if (sm->wpa == WPA_VERSION_WPA)
Hai Shalome21d4e82020-04-29 16:34:06 -07003733 sm->PInitAKeys = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003734 else
Hai Shalome21d4e82020-04-29 16:34:06 -07003735 sm->has_GTK = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003736 wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO,
3737 "pairwise key handshake completed (%s)",
3738 sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN");
Hai Shaloma20dcd72022-02-04 13:43:00 -08003739 wpa_msg(sm->wpa_auth->conf.msg_ctx, MSG_INFO, "EAPOL-4WAY-HS-COMPLETED "
3740 MACSTR, MAC2STR(sm->addr));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003741
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003742#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003743 wpa_ft_push_pmk_r1(sm->wpa_auth, sm->addr);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003744#endif /* CONFIG_IEEE80211R_AP */
Sunil Ravia04bd252022-05-02 22:54:18 -07003745
3746 sm->ptkstart_without_success = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003747}
3748
3749
3750SM_STEP(WPA_PTK)
3751{
3752 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
Hai Shalomfdcde762020-04-02 11:19:20 -07003753 struct wpa_auth_config *conf = &wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003754
3755 if (sm->Init)
3756 SM_ENTER(WPA_PTK, INITIALIZE);
3757 else if (sm->Disconnect
3758 /* || FIX: dot11RSNAConfigSALifetime timeout */) {
3759 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
3760 "WPA_PTK: sm->Disconnect");
3761 SM_ENTER(WPA_PTK, DISCONNECT);
3762 }
3763 else if (sm->DeauthenticationRequest)
3764 SM_ENTER(WPA_PTK, DISCONNECTED);
3765 else if (sm->AuthenticationRequest)
3766 SM_ENTER(WPA_PTK, AUTHENTICATION);
3767 else if (sm->ReAuthenticationRequest)
3768 SM_ENTER(WPA_PTK, AUTHENTICATION2);
Jouni Malinen1420a892017-10-01 12:32:57 +03003769 else if (sm->PTKRequest) {
3770 if (wpa_auth_sm_ptk_update(sm) < 0)
3771 SM_ENTER(WPA_PTK, DISCONNECTED);
3772 else
3773 SM_ENTER(WPA_PTK, PTKSTART);
3774 } else switch (sm->wpa_ptk_state) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003775 case WPA_PTK_INITIALIZE:
3776 break;
3777 case WPA_PTK_DISCONNECT:
3778 SM_ENTER(WPA_PTK, DISCONNECTED);
3779 break;
3780 case WPA_PTK_DISCONNECTED:
3781 SM_ENTER(WPA_PTK, INITIALIZE);
3782 break;
3783 case WPA_PTK_AUTHENTICATION:
3784 SM_ENTER(WPA_PTK, AUTHENTICATION2);
3785 break;
3786 case WPA_PTK_AUTHENTICATION2:
3787 if (wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) &&
Hai Shalomfdcde762020-04-02 11:19:20 -07003788 wpa_auth_get_eapol(wpa_auth, sm->addr,
Hai Shalome21d4e82020-04-29 16:34:06 -07003789 WPA_EAPOL_keyRun))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003790 SM_ENTER(WPA_PTK, INITPMK);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003791 else if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
3792 sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003793 /* FIX: && 802.1X::keyRun */)
3794 SM_ENTER(WPA_PTK, INITPSK);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003795 else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP)
3796 SM_ENTER(WPA_PTK, INITPMK);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003797 break;
3798 case WPA_PTK_INITPMK:
Hai Shalomfdcde762020-04-02 11:19:20 -07003799 if (wpa_auth_get_eapol(wpa_auth, sm->addr,
Hai Shalome21d4e82020-04-29 16:34:06 -07003800 WPA_EAPOL_keyAvailable)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003801 SM_ENTER(WPA_PTK, PTKSTART);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003802#ifdef CONFIG_DPP
3803 } else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP && sm->pmksa) {
3804 SM_ENTER(WPA_PTK, PTKSTART);
3805#endif /* CONFIG_DPP */
3806 } else {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003807 wpa_auth->dot11RSNA4WayHandshakeFailures++;
Hai Shalomfdcde762020-04-02 11:19:20 -07003808 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003809 "INITPMK - keyAvailable = false");
3810 SM_ENTER(WPA_PTK, DISCONNECT);
3811 }
3812 break;
3813 case WPA_PTK_INITPSK:
Hai Shalomfdcde762020-04-02 11:19:20 -07003814 if (wpa_auth_get_psk(wpa_auth, sm->addr, sm->p2p_dev_addr,
Hai Shalom021b0b52019-04-10 11:17:58 -07003815 NULL, NULL, NULL)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003816 SM_ENTER(WPA_PTK, PTKSTART);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003817#ifdef CONFIG_SAE
3818 } else if (wpa_auth_uses_sae(sm) && sm->pmksa) {
3819 SM_ENTER(WPA_PTK, PTKSTART);
3820#endif /* CONFIG_SAE */
Sunil Ravia04bd252022-05-02 22:54:18 -07003821 } else if (wpa_key_mgmt_wpa_psk_no_sae(sm->wpa_key_mgmt) &&
3822 wpa_auth->conf.radius_psk) {
3823 wpa_printf(MSG_DEBUG,
3824 "INITPSK: No PSK yet available for STA - use RADIUS later");
3825 SM_ENTER(WPA_PTK, PTKSTART);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003826 } else {
Hai Shalomfdcde762020-04-02 11:19:20 -07003827 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003828 "no PSK configured for the STA");
3829 wpa_auth->dot11RSNA4WayHandshakeFailures++;
3830 SM_ENTER(WPA_PTK, DISCONNECT);
3831 }
3832 break;
3833 case WPA_PTK_PTKSTART:
3834 if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest &&
3835 sm->EAPOLKeyPairwise)
3836 SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING);
Hai Shalomfdcde762020-04-02 11:19:20 -07003837 else if (sm->TimeoutCtr > conf->wpa_pairwise_update_count) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003838 wpa_auth->dot11RSNA4WayHandshakeFailures++;
Hai Shalomfdcde762020-04-02 11:19:20 -07003839 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
3840 "PTKSTART: Retry limit %u reached",
3841 conf->wpa_pairwise_update_count);
Hai Shalome21d4e82020-04-29 16:34:06 -07003842 sm->disconnect_reason =
3843 WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003844 SM_ENTER(WPA_PTK, DISCONNECT);
3845 } else if (sm->TimeoutEvt)
3846 SM_ENTER(WPA_PTK, PTKSTART);
3847 break;
3848 case WPA_PTK_PTKCALCNEGOTIATING:
3849 if (sm->MICVerified)
3850 SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING2);
3851 else if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest &&
3852 sm->EAPOLKeyPairwise)
3853 SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING);
3854 else if (sm->TimeoutEvt)
3855 SM_ENTER(WPA_PTK, PTKSTART);
3856 break;
3857 case WPA_PTK_PTKCALCNEGOTIATING2:
3858 SM_ENTER(WPA_PTK, PTKINITNEGOTIATING);
3859 break;
3860 case WPA_PTK_PTKINITNEGOTIATING:
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003861 if (sm->update_snonce)
3862 SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING);
3863 else if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest &&
3864 sm->EAPOLKeyPairwise && sm->MICVerified)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003865 SM_ENTER(WPA_PTK, PTKINITDONE);
3866 else if (sm->TimeoutCtr >
Hai Shalomfdcde762020-04-02 11:19:20 -07003867 conf->wpa_pairwise_update_count ||
3868 (conf->wpa_disable_eapol_key_retries &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003869 sm->TimeoutCtr > 1)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003870 wpa_auth->dot11RSNA4WayHandshakeFailures++;
Hai Shalomfdcde762020-04-02 11:19:20 -07003871 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
3872 "PTKINITNEGOTIATING: Retry limit %u reached",
3873 conf->wpa_pairwise_update_count);
Hai Shalome21d4e82020-04-29 16:34:06 -07003874 sm->disconnect_reason =
3875 WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003876 SM_ENTER(WPA_PTK, DISCONNECT);
3877 } else if (sm->TimeoutEvt)
3878 SM_ENTER(WPA_PTK, PTKINITNEGOTIATING);
3879 break;
3880 case WPA_PTK_PTKINITDONE:
3881 break;
3882 }
3883}
3884
3885
3886SM_STATE(WPA_PTK_GROUP, IDLE)
3887{
3888 SM_ENTRY_MA(WPA_PTK_GROUP, IDLE, wpa_ptk_group);
3889 if (sm->Init) {
3890 /* Init flag is not cleared here, so avoid busy
3891 * loop by claiming nothing changed. */
Hai Shalome21d4e82020-04-29 16:34:06 -07003892 sm->changed = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003893 }
3894 sm->GTimeoutCtr = 0;
3895}
3896
3897
3898SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING)
3899{
3900 u8 rsc[WPA_KEY_RSC_LEN];
3901 struct wpa_group *gsm = sm->group;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003902 const u8 *kde;
3903 u8 *kde_buf = NULL, *pos, hdr[2];
Sunil Ravia04bd252022-05-02 22:54:18 -07003904 size_t kde_len = 0;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003905 u8 *gtk, stub_gtk[32];
Hai Shalomfdcde762020-04-02 11:19:20 -07003906 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003907
3908 SM_ENTRY_MA(WPA_PTK_GROUP, REKEYNEGOTIATING, wpa_ptk_group);
3909
3910 sm->GTimeoutCtr++;
Hai Shalomfdcde762020-04-02 11:19:20 -07003911 if (conf->wpa_disable_eapol_key_retries && sm->GTimeoutCtr > 1) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003912 /* Do not allow retransmission of EAPOL-Key group msg 1/2 */
3913 return;
3914 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003915 if (sm->GTimeoutCtr > conf->wpa_group_update_count) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003916 /* No point in sending the EAPOL-Key - we will disconnect
3917 * immediately following this. */
3918 return;
3919 }
3920
3921 if (sm->wpa == WPA_VERSION_WPA)
Hai Shalome21d4e82020-04-29 16:34:06 -07003922 sm->PInitAKeys = false;
3923 sm->TimeoutEvt = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003924 /* Send EAPOL(1, 1, 1, !Pair, G, RSC, GNonce, MIC(PTK), GTK[GN]) */
3925 os_memset(rsc, 0, WPA_KEY_RSC_LEN);
3926 if (gsm->wpa_group_state == WPA_GROUP_SETKEYSDONE)
3927 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc);
3928 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
3929 "sending 1/2 msg of Group Key Handshake");
3930
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003931 gtk = gsm->GTK[gsm->GN - 1];
Hai Shalomfdcde762020-04-02 11:19:20 -07003932 if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003933 /*
3934 * Provide unique random GTK to each STA to prevent use
3935 * of GTK in the BSS.
3936 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003937 if (random_get_bytes(stub_gtk, gsm->GTK_len) < 0)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003938 return;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003939 gtk = stub_gtk;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003940 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003941 if (sm->wpa == WPA_VERSION_WPA2) {
3942 kde_len = 2 + RSN_SELECTOR_LEN + 2 + gsm->GTK_len +
Hai Shalom74f70d42019-02-11 14:42:39 -08003943 ieee80211w_kde_len(sm) + ocv_oci_len(sm);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003944 kde_buf = os_malloc(kde_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07003945 if (!kde_buf)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003946 return;
3947
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003948 kde = pos = kde_buf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003949 hdr[0] = gsm->GN & 0x03;
3950 hdr[1] = 0;
3951 pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003952 gtk, gsm->GTK_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003953 pos = ieee80211w_kde_add(sm, pos);
Hai Shalom899fcc72020-10-19 14:38:18 -07003954 if (ocv_oci_add(sm, &pos,
3955 conf->oci_freq_override_eapol_g1) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -08003956 os_free(kde_buf);
3957 return;
3958 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003959 kde_len = pos - kde;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003960 } else {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003961 kde = gtk;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003962 kde_len = gsm->GTK_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003963 }
3964
3965 wpa_send_eapol(sm->wpa_auth, sm,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003966 WPA_KEY_INFO_SECURE |
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003967 (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
3968 WPA_KEY_INFO_MIC : 0) |
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003969 WPA_KEY_INFO_ACK |
3970 (!sm->Pair ? WPA_KEY_INFO_INSTALL : 0),
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003971 rsc, NULL, kde, kde_len, gsm->GN, 1);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003972
Sunil Ravia04bd252022-05-02 22:54:18 -07003973 bin_clear_free(kde_buf, kde_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003974}
3975
3976
3977SM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED)
3978{
Hai Shalom74f70d42019-02-11 14:42:39 -08003979 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
Hai Shalomfdcde762020-04-02 11:19:20 -07003980#ifdef CONFIG_OCV
Hai Shalom74f70d42019-02-11 14:42:39 -08003981 const u8 *key_data, *mic;
3982 struct ieee802_1x_hdr *hdr;
3983 struct wpa_eapol_key *key;
3984 struct wpa_eapol_ie_parse kde;
3985 size_t mic_len;
3986 u16 key_data_length;
3987#endif /* CONFIG_OCV */
3988
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003989 SM_ENTRY_MA(WPA_PTK_GROUP, REKEYESTABLISHED, wpa_ptk_group);
Hai Shalome21d4e82020-04-29 16:34:06 -07003990 sm->EAPOLKeyReceived = false;
Hai Shalom74f70d42019-02-11 14:42:39 -08003991
3992#ifdef CONFIG_OCV
3993 mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
3994
3995 /*
3996 * Note: last_rx_eapol_key length fields have already been validated in
3997 * wpa_receive().
3998 */
3999 hdr = (struct ieee802_1x_hdr *) sm->last_rx_eapol_key;
4000 key = (struct wpa_eapol_key *) (hdr + 1);
4001 mic = (u8 *) (key + 1);
4002 key_data = mic + mic_len + 2;
4003 key_data_length = WPA_GET_BE16(mic + mic_len);
4004 if (key_data_length > sm->last_rx_eapol_key_len - sizeof(*hdr) -
4005 sizeof(*key) - mic_len - 2)
4006 return;
4007
4008 if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) {
4009 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
4010 "received EAPOL-Key group msg 2/2 with invalid Key Data contents");
4011 return;
4012 }
4013
4014 if (wpa_auth_uses_ocv(sm)) {
4015 struct wpa_channel_info ci;
4016 int tx_chanwidth;
4017 int tx_seg1_idx;
4018
4019 if (wpa_channel_info(wpa_auth, &ci) != 0) {
4020 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalom899fcc72020-10-19 14:38:18 -07004021 "Failed to get channel info to validate received OCI in EAPOL-Key group 2/2");
Hai Shalom74f70d42019-02-11 14:42:39 -08004022 return;
4023 }
4024
4025 if (get_sta_tx_parameters(sm,
4026 channel_width_to_int(ci.chanwidth),
4027 ci.seg1_idx, &tx_chanwidth,
4028 &tx_seg1_idx) < 0)
4029 return;
4030
4031 if (ocv_verify_tx_params(kde.oci, kde.oci_len, &ci,
Hai Shalom899fcc72020-10-19 14:38:18 -07004032 tx_chanwidth, tx_seg1_idx) !=
4033 OCI_SUCCESS) {
4034 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
4035 "OCV failed: %s", ocv_errorstr);
4036 if (wpa_auth->conf.msg_ctx)
4037 wpa_msg(wpa_auth->conf.msg_ctx, MSG_INFO,
4038 OCV_FAILURE "addr=" MACSTR
4039 " frame=eapol-key-g2 error=%s",
4040 MAC2STR(sm->addr), ocv_errorstr);
Hai Shalom74f70d42019-02-11 14:42:39 -08004041 return;
4042 }
4043 }
4044#endif /* CONFIG_OCV */
4045
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004046 if (sm->GUpdateStationKeys)
4047 sm->group->GKeyDoneStations--;
Hai Shalome21d4e82020-04-29 16:34:06 -07004048 sm->GUpdateStationKeys = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004049 sm->GTimeoutCtr = 0;
4050 /* FIX: MLME.SetProtection.Request(TA, Tx_Rx) */
Hai Shalomfdcde762020-04-02 11:19:20 -07004051 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004052 "group key handshake completed (%s)",
4053 sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN");
Hai Shalome21d4e82020-04-29 16:34:06 -07004054 sm->has_GTK = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004055}
4056
4057
4058SM_STATE(WPA_PTK_GROUP, KEYERROR)
4059{
4060 SM_ENTRY_MA(WPA_PTK_GROUP, KEYERROR, wpa_ptk_group);
4061 if (sm->GUpdateStationKeys)
4062 sm->group->GKeyDoneStations--;
Hai Shalome21d4e82020-04-29 16:34:06 -07004063 sm->GUpdateStationKeys = false;
4064 sm->Disconnect = true;
4065 sm->disconnect_reason = WLAN_REASON_GROUP_KEY_UPDATE_TIMEOUT;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004066 wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO,
4067 "group key handshake failed (%s) after %u tries",
4068 sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN",
4069 sm->wpa_auth->conf.wpa_group_update_count);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004070}
4071
4072
4073SM_STEP(WPA_PTK_GROUP)
4074{
4075 if (sm->Init || sm->PtkGroupInit) {
4076 SM_ENTER(WPA_PTK_GROUP, IDLE);
Hai Shalome21d4e82020-04-29 16:34:06 -07004077 sm->PtkGroupInit = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004078 } else switch (sm->wpa_ptk_group_state) {
4079 case WPA_PTK_GROUP_IDLE:
4080 if (sm->GUpdateStationKeys ||
4081 (sm->wpa == WPA_VERSION_WPA && sm->PInitAKeys))
4082 SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING);
4083 break;
4084 case WPA_PTK_GROUP_REKEYNEGOTIATING:
4085 if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest &&
4086 !sm->EAPOLKeyPairwise && sm->MICVerified)
4087 SM_ENTER(WPA_PTK_GROUP, REKEYESTABLISHED);
4088 else if (sm->GTimeoutCtr >
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004089 sm->wpa_auth->conf.wpa_group_update_count ||
4090 (sm->wpa_auth->conf.wpa_disable_eapol_key_retries &&
4091 sm->GTimeoutCtr > 1))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004092 SM_ENTER(WPA_PTK_GROUP, KEYERROR);
4093 else if (sm->TimeoutEvt)
4094 SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING);
4095 break;
4096 case WPA_PTK_GROUP_KEYERROR:
4097 SM_ENTER(WPA_PTK_GROUP, IDLE);
4098 break;
4099 case WPA_PTK_GROUP_REKEYESTABLISHED:
4100 SM_ENTER(WPA_PTK_GROUP, IDLE);
4101 break;
4102 }
4103}
4104
4105
4106static int wpa_gtk_update(struct wpa_authenticator *wpa_auth,
4107 struct wpa_group *group)
4108{
Hai Shalomfdcde762020-04-02 11:19:20 -07004109 struct wpa_auth_config *conf = &wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004110 int ret = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07004111 size_t len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004112
4113 os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
4114 inc_byte_array(group->Counter, WPA_NONCE_LEN);
4115 if (wpa_gmk_to_gtk(group->GMK, "Group key expansion",
4116 wpa_auth->addr, group->GNonce,
4117 group->GTK[group->GN - 1], group->GTK_len) < 0)
4118 ret = -1;
4119 wpa_hexdump_key(MSG_DEBUG, "GTK",
4120 group->GTK[group->GN - 1], group->GTK_len);
4121
Hai Shalomfdcde762020-04-02 11:19:20 -07004122 if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
4123 len = wpa_cipher_key_len(conf->group_mgmt_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004124 os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
4125 inc_byte_array(group->Counter, WPA_NONCE_LEN);
4126 if (wpa_gmk_to_gtk(group->GMK, "IGTK key expansion",
4127 wpa_auth->addr, group->GNonce,
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004128 group->IGTK[group->GN_igtk - 4], len) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004129 ret = -1;
4130 wpa_hexdump_key(MSG_DEBUG, "IGTK",
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004131 group->IGTK[group->GN_igtk - 4], len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004132 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004133
Hai Shalomfdcde762020-04-02 11:19:20 -07004134 if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION &&
4135 conf->beacon_prot) {
4136 len = wpa_cipher_key_len(conf->group_mgmt_cipher);
4137 os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
4138 inc_byte_array(group->Counter, WPA_NONCE_LEN);
4139 if (wpa_gmk_to_gtk(group->GMK, "BIGTK key expansion",
4140 wpa_auth->addr, group->GNonce,
4141 group->BIGTK[group->GN_bigtk - 6], len) < 0)
4142 ret = -1;
4143 wpa_hexdump_key(MSG_DEBUG, "BIGTK",
4144 group->BIGTK[group->GN_bigtk - 6], len);
4145 }
4146
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004147 return ret;
4148}
4149
4150
4151static void wpa_group_gtk_init(struct wpa_authenticator *wpa_auth,
4152 struct wpa_group *group)
4153{
Hai Shalomfdcde762020-04-02 11:19:20 -07004154 wpa_printf(MSG_DEBUG,
4155 "WPA: group state machine entering state GTK_INIT (VLAN-ID %d)",
4156 group->vlan_id);
Hai Shalome21d4e82020-04-29 16:34:06 -07004157 group->changed = false; /* GInit is not cleared here; avoid loop */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004158 group->wpa_group_state = WPA_GROUP_GTK_INIT;
4159
4160 /* GTK[0..N] = 0 */
4161 os_memset(group->GTK, 0, sizeof(group->GTK));
4162 group->GN = 1;
4163 group->GM = 2;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004164 group->GN_igtk = 4;
4165 group->GM_igtk = 5;
Hai Shalomfdcde762020-04-02 11:19:20 -07004166 group->GN_bigtk = 6;
4167 group->GM_bigtk = 7;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004168 /* GTK[GN] = CalcGTK() */
4169 wpa_gtk_update(wpa_auth, group);
4170}
4171
4172
4173static int wpa_group_update_sta(struct wpa_state_machine *sm, void *ctx)
4174{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004175 if (ctx != NULL && ctx != sm->group)
4176 return 0;
4177
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004178 if (sm->wpa_ptk_state != WPA_PTK_PTKINITDONE) {
4179 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
4180 "Not in PTKINITDONE; skip Group Key update");
Hai Shalome21d4e82020-04-29 16:34:06 -07004181 sm->GUpdateStationKeys = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004182 return 0;
4183 }
4184 if (sm->GUpdateStationKeys) {
4185 /*
4186 * This should not really happen, so add a debug log entry.
4187 * Since we clear the GKeyDoneStations before the loop, the
4188 * station needs to be counted here anyway.
4189 */
4190 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07004191 "GUpdateStationKeys was already set when marking station for GTK rekeying");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004192 }
4193
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004194 /* Do not rekey GTK/IGTK when STA is in WNM-Sleep Mode */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004195 if (sm->is_wnmsleep)
4196 return 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004197
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004198 sm->group->GKeyDoneStations++;
Hai Shalome21d4e82020-04-29 16:34:06 -07004199 sm->GUpdateStationKeys = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004200
4201 wpa_sm_step(sm);
4202 return 0;
4203}
4204
4205
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004206#ifdef CONFIG_WNM_AP
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004207/* update GTK when exiting WNM-Sleep Mode */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004208void wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm)
4209{
Hai Shalomfdcde762020-04-02 11:19:20 -07004210 if (!sm || sm->is_wnmsleep)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004211 return;
4212
4213 wpa_group_update_sta(sm, NULL);
4214}
4215
4216
4217void wpa_set_wnmsleep(struct wpa_state_machine *sm, int flag)
4218{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004219 if (sm)
4220 sm->is_wnmsleep = !!flag;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004221}
4222
4223
4224int wpa_wnmsleep_gtk_subelem(struct wpa_state_machine *sm, u8 *pos)
4225{
Hai Shalom899fcc72020-10-19 14:38:18 -07004226 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004227 struct wpa_group *gsm = sm->group;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004228 u8 *start = pos;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004229
4230 /*
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004231 * GTK subelement:
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004232 * Sub-elem ID[1] | Length[1] | Key Info[2] | Key Length[1] | RSC[8] |
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004233 * Key[5..32]
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004234 */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004235 *pos++ = WNM_SLEEP_SUBELEM_GTK;
4236 *pos++ = 11 + gsm->GTK_len;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004237 /* Key ID in B0-B1 of Key Info */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004238 WPA_PUT_LE16(pos, gsm->GN & 0x03);
4239 pos += 2;
4240 *pos++ = gsm->GTK_len;
4241 if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, pos) != 0)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004242 return 0;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004243 pos += 8;
4244 os_memcpy(pos, gsm->GTK[gsm->GN - 1], gsm->GTK_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07004245 if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
4246 /*
4247 * Provide unique random GTK to each STA to prevent use
4248 * of GTK in the BSS.
4249 */
4250 if (random_get_bytes(pos, gsm->GTK_len) < 0)
4251 return 0;
4252 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004253 pos += gsm->GTK_len;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004254
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004255 wpa_printf(MSG_DEBUG, "WNM: GTK Key ID %u in WNM-Sleep Mode exit",
4256 gsm->GN);
4257 wpa_hexdump_key(MSG_DEBUG, "WNM: GTK in WNM-Sleep Mode exit",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004258 gsm->GTK[gsm->GN - 1], gsm->GTK_len);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004259
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004260 return pos - start;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004261}
4262
4263
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004264int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos)
4265{
Hai Shalom899fcc72020-10-19 14:38:18 -07004266 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004267 struct wpa_group *gsm = sm->group;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004268 u8 *start = pos;
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004269 size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004270
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004271 /*
4272 * IGTK subelement:
4273 * Sub-elem ID[1] | Length[1] | KeyID[2] | PN[6] | Key[16]
4274 */
4275 *pos++ = WNM_SLEEP_SUBELEM_IGTK;
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004276 *pos++ = 2 + 6 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004277 WPA_PUT_LE16(pos, gsm->GN_igtk);
4278 pos += 2;
4279 if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, pos) != 0)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004280 return 0;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004281 pos += 6;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004282
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004283 os_memcpy(pos, gsm->IGTK[gsm->GN_igtk - 4], len);
Hai Shalom899fcc72020-10-19 14:38:18 -07004284 if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
4285 /*
4286 * Provide unique random IGTK to each STA to prevent use
4287 * of IGTK in the BSS.
4288 */
4289 if (random_get_bytes(pos, len) < 0)
4290 return 0;
4291 }
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004292 pos += len;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004293
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004294 wpa_printf(MSG_DEBUG, "WNM: IGTK Key ID %u in WNM-Sleep Mode exit",
4295 gsm->GN_igtk);
4296 wpa_hexdump_key(MSG_DEBUG, "WNM: IGTK in WNM-Sleep Mode exit",
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004297 gsm->IGTK[gsm->GN_igtk - 4], len);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004298
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004299 return pos - start;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004300}
Hai Shalomc3565922019-10-28 11:58:20 -07004301
Hai Shalomfdcde762020-04-02 11:19:20 -07004302
4303int wpa_wnmsleep_bigtk_subelem(struct wpa_state_machine *sm, u8 *pos)
4304{
4305 struct wpa_group *gsm = sm->group;
4306 u8 *start = pos;
4307 size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
4308
4309 /*
4310 * BIGTK subelement:
4311 * Sub-elem ID[1] | Length[1] | KeyID[2] | PN[6] | Key[16]
4312 */
4313 *pos++ = WNM_SLEEP_SUBELEM_BIGTK;
4314 *pos++ = 2 + 6 + len;
4315 WPA_PUT_LE16(pos, gsm->GN_bigtk);
4316 pos += 2;
4317 if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_bigtk, pos) != 0)
4318 return 0;
4319 pos += 6;
4320
4321 os_memcpy(pos, gsm->BIGTK[gsm->GN_bigtk - 6], len);
Hai Shalom899fcc72020-10-19 14:38:18 -07004322 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
4323 /*
4324 * Provide unique random BIGTK to each STA to prevent use
4325 * of BIGTK in the BSS.
4326 */
4327 if (random_get_bytes(pos, len) < 0)
4328 return 0;
4329 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004330 pos += len;
4331
4332 wpa_printf(MSG_DEBUG, "WNM: BIGTK Key ID %u in WNM-Sleep Mode exit",
4333 gsm->GN_bigtk);
4334 wpa_hexdump_key(MSG_DEBUG, "WNM: BIGTK in WNM-Sleep Mode exit",
Hai Shaloma20dcd72022-02-04 13:43:00 -08004335 gsm->BIGTK[gsm->GN_bigtk - 6], len);
Hai Shalomfdcde762020-04-02 11:19:20 -07004336
4337 return pos - start;
4338}
4339
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004340#endif /* CONFIG_WNM_AP */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004341
4342
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004343static void wpa_group_setkeys(struct wpa_authenticator *wpa_auth,
4344 struct wpa_group *group)
4345{
4346 int tmp;
4347
Hai Shalomfdcde762020-04-02 11:19:20 -07004348 wpa_printf(MSG_DEBUG,
4349 "WPA: group state machine entering state SETKEYS (VLAN-ID %d)",
4350 group->vlan_id);
Hai Shalome21d4e82020-04-29 16:34:06 -07004351 group->changed = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004352 group->wpa_group_state = WPA_GROUP_SETKEYS;
Hai Shalome21d4e82020-04-29 16:34:06 -07004353 group->GTKReKey = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004354 tmp = group->GM;
4355 group->GM = group->GN;
4356 group->GN = tmp;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004357 tmp = group->GM_igtk;
4358 group->GM_igtk = group->GN_igtk;
4359 group->GN_igtk = tmp;
Hai Shalomfdcde762020-04-02 11:19:20 -07004360 tmp = group->GM_bigtk;
4361 group->GM_bigtk = group->GN_bigtk;
4362 group->GN_bigtk = tmp;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004363 /* "GKeyDoneStations = GNoStations" is done in more robust way by
4364 * counting the STAs that are marked with GUpdateStationKeys instead of
4365 * including all STAs that could be in not-yet-completed state. */
4366 wpa_gtk_update(wpa_auth, group);
4367
4368 if (group->GKeyDoneStations) {
Hai Shalomfdcde762020-04-02 11:19:20 -07004369 wpa_printf(MSG_DEBUG,
4370 "wpa_group_setkeys: Unexpected GKeyDoneStations=%d when starting new GTK rekey",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004371 group->GKeyDoneStations);
4372 group->GKeyDoneStations = 0;
4373 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004374 wpa_auth_for_each_sta(wpa_auth, wpa_group_update_sta, group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004375 wpa_printf(MSG_DEBUG, "wpa_group_setkeys: GKeyDoneStations=%d",
4376 group->GKeyDoneStations);
4377}
4378
4379
4380static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth,
4381 struct wpa_group *group)
4382{
Hai Shalomfdcde762020-04-02 11:19:20 -07004383 struct wpa_auth_config *conf = &wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004384 int ret = 0;
4385
4386 if (wpa_auth_set_key(wpa_auth, group->vlan_id,
Hai Shalomfdcde762020-04-02 11:19:20 -07004387 wpa_cipher_to_alg(conf->wpa_group),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004388 broadcast_ether_addr, group->GN,
Hai Shalomfdcde762020-04-02 11:19:20 -07004389 group->GTK[group->GN - 1], group->GTK_len,
4390 KEY_FLAG_GROUP_TX_DEFAULT) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004391 ret = -1;
4392
Hai Shalomfdcde762020-04-02 11:19:20 -07004393 if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004394 enum wpa_alg alg;
4395 size_t len;
4396
Hai Shalomfdcde762020-04-02 11:19:20 -07004397 alg = wpa_cipher_to_alg(conf->group_mgmt_cipher);
4398 len = wpa_cipher_key_len(conf->group_mgmt_cipher);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004399
4400 if (ret == 0 &&
4401 wpa_auth_set_key(wpa_auth, group->vlan_id, alg,
4402 broadcast_ether_addr, group->GN_igtk,
Hai Shalomfdcde762020-04-02 11:19:20 -07004403 group->IGTK[group->GN_igtk - 4], len,
4404 KEY_FLAG_GROUP_TX_DEFAULT) < 0)
4405 ret = -1;
4406
4407 if (ret == 0 && conf->beacon_prot &&
4408 wpa_auth_set_key(wpa_auth, group->vlan_id, alg,
4409 broadcast_ether_addr, group->GN_bigtk,
4410 group->BIGTK[group->GN_bigtk - 6], len,
4411 KEY_FLAG_GROUP_TX_DEFAULT) < 0)
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004412 ret = -1;
4413 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004414
4415 return ret;
4416}
4417
4418
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004419static int wpa_group_disconnect_cb(struct wpa_state_machine *sm, void *ctx)
4420{
4421 if (sm->group == ctx) {
4422 wpa_printf(MSG_DEBUG, "WPA: Mark STA " MACSTR
Hai Shalomfdcde762020-04-02 11:19:20 -07004423 " for disconnection due to fatal failure",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004424 MAC2STR(sm->addr));
Hai Shalome21d4e82020-04-29 16:34:06 -07004425 sm->Disconnect = true;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004426 }
4427
4428 return 0;
4429}
4430
4431
4432static void wpa_group_fatal_failure(struct wpa_authenticator *wpa_auth,
4433 struct wpa_group *group)
4434{
Hai Shalomfdcde762020-04-02 11:19:20 -07004435 wpa_printf(MSG_DEBUG,
4436 "WPA: group state machine entering state FATAL_FAILURE");
Hai Shalome21d4e82020-04-29 16:34:06 -07004437 group->changed = true;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004438 group->wpa_group_state = WPA_GROUP_FATAL_FAILURE;
4439 wpa_auth_for_each_sta(wpa_auth, wpa_group_disconnect_cb, group);
4440}
4441
4442
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004443static int wpa_group_setkeysdone(struct wpa_authenticator *wpa_auth,
4444 struct wpa_group *group)
4445{
Hai Shalomfdcde762020-04-02 11:19:20 -07004446 wpa_printf(MSG_DEBUG,
4447 "WPA: group state machine entering state SETKEYSDONE (VLAN-ID %d)",
4448 group->vlan_id);
Hai Shalome21d4e82020-04-29 16:34:06 -07004449 group->changed = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004450 group->wpa_group_state = WPA_GROUP_SETKEYSDONE;
4451
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004452 if (wpa_group_config_group_keys(wpa_auth, group) < 0) {
4453 wpa_group_fatal_failure(wpa_auth, group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004454 return -1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004455 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004456
4457 return 0;
4458}
4459
4460
4461static void wpa_group_sm_step(struct wpa_authenticator *wpa_auth,
4462 struct wpa_group *group)
4463{
4464 if (group->GInit) {
4465 wpa_group_gtk_init(wpa_auth, group);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004466 } else if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) {
4467 /* Do not allow group operations */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004468 } else if (group->wpa_group_state == WPA_GROUP_GTK_INIT &&
4469 group->GTKAuthenticator) {
4470 wpa_group_setkeysdone(wpa_auth, group);
4471 } else if (group->wpa_group_state == WPA_GROUP_SETKEYSDONE &&
4472 group->GTKReKey) {
4473 wpa_group_setkeys(wpa_auth, group);
4474 } else if (group->wpa_group_state == WPA_GROUP_SETKEYS) {
4475 if (group->GKeyDoneStations == 0)
4476 wpa_group_setkeysdone(wpa_auth, group);
4477 else if (group->GTKReKey)
4478 wpa_group_setkeys(wpa_auth, group);
4479 }
4480}
4481
4482
4483static int wpa_sm_step(struct wpa_state_machine *sm)
4484{
Hai Shalomfdcde762020-04-02 11:19:20 -07004485 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004486 return 0;
4487
4488 if (sm->in_step_loop) {
4489 /* This should not happen, but if it does, make sure we do not
4490 * end up freeing the state machine too early by exiting the
4491 * recursive call. */
4492 wpa_printf(MSG_ERROR, "WPA: wpa_sm_step() called recursively");
4493 return 0;
4494 }
4495
4496 sm->in_step_loop = 1;
4497 do {
4498 if (sm->pending_deinit)
4499 break;
4500
Hai Shalome21d4e82020-04-29 16:34:06 -07004501 sm->changed = false;
4502 sm->wpa_auth->group->changed = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004503
4504 SM_STEP_RUN(WPA_PTK);
4505 if (sm->pending_deinit)
4506 break;
4507 SM_STEP_RUN(WPA_PTK_GROUP);
4508 if (sm->pending_deinit)
4509 break;
4510 wpa_group_sm_step(sm->wpa_auth, sm->group);
4511 } while (sm->changed || sm->wpa_auth->group->changed);
4512 sm->in_step_loop = 0;
4513
4514 if (sm->pending_deinit) {
Hai Shalomfdcde762020-04-02 11:19:20 -07004515 wpa_printf(MSG_DEBUG,
4516 "WPA: Completing pending STA state machine deinit for "
4517 MACSTR, MAC2STR(sm->addr));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004518 wpa_free_sta_sm(sm);
4519 return 1;
4520 }
4521 return 0;
4522}
4523
4524
4525static void wpa_sm_call_step(void *eloop_ctx, void *timeout_ctx)
4526{
4527 struct wpa_state_machine *sm = eloop_ctx;
4528 wpa_sm_step(sm);
4529}
4530
4531
4532void wpa_auth_sm_notify(struct wpa_state_machine *sm)
4533{
Hai Shalomfdcde762020-04-02 11:19:20 -07004534 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004535 return;
4536 eloop_register_timeout(0, 0, wpa_sm_call_step, sm, NULL);
4537}
4538
4539
4540void wpa_gtk_rekey(struct wpa_authenticator *wpa_auth)
4541{
4542 int tmp, i;
4543 struct wpa_group *group;
4544
Hai Shalomfdcde762020-04-02 11:19:20 -07004545 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004546 return;
4547
4548 group = wpa_auth->group;
4549
4550 for (i = 0; i < 2; i++) {
4551 tmp = group->GM;
4552 group->GM = group->GN;
4553 group->GN = tmp;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004554 tmp = group->GM_igtk;
4555 group->GM_igtk = group->GN_igtk;
4556 group->GN_igtk = tmp;
Hai Shalomfdcde762020-04-02 11:19:20 -07004557 tmp = group->GM_bigtk;
4558 group->GM_bigtk = group->GN_bigtk;
4559 group->GN_bigtk = tmp;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004560 wpa_gtk_update(wpa_auth, group);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004561 wpa_group_config_group_keys(wpa_auth, group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004562 }
4563}
4564
4565
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004566static const char * wpa_bool_txt(int val)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004567{
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004568 return val ? "TRUE" : "FALSE";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004569}
4570
4571
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004572#define RSN_SUITE "%02x-%02x-%02x-%d"
4573#define RSN_SUITE_ARG(s) \
4574((s) >> 24) & 0xff, ((s) >> 16) & 0xff, ((s) >> 8) & 0xff, (s) & 0xff
4575
4576int wpa_get_mib(struct wpa_authenticator *wpa_auth, char *buf, size_t buflen)
4577{
Hai Shalomfdcde762020-04-02 11:19:20 -07004578 struct wpa_auth_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004579 int len = 0, ret;
4580 char pmkid_txt[PMKID_LEN * 2 + 1];
4581#ifdef CONFIG_RSN_PREAUTH
4582 const int preauth = 1;
4583#else /* CONFIG_RSN_PREAUTH */
4584 const int preauth = 0;
4585#endif /* CONFIG_RSN_PREAUTH */
4586
Hai Shalomfdcde762020-04-02 11:19:20 -07004587 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004588 return len;
Hai Shalomfdcde762020-04-02 11:19:20 -07004589 conf = &wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004590
4591 ret = os_snprintf(buf + len, buflen - len,
4592 "dot11RSNAOptionImplemented=TRUE\n"
4593 "dot11RSNAPreauthenticationImplemented=%s\n"
4594 "dot11RSNAEnabled=%s\n"
4595 "dot11RSNAPreauthenticationEnabled=%s\n",
4596 wpa_bool_txt(preauth),
Hai Shalomfdcde762020-04-02 11:19:20 -07004597 wpa_bool_txt(conf->wpa & WPA_PROTO_RSN),
4598 wpa_bool_txt(conf->rsn_preauth));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004599 if (os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004600 return len;
4601 len += ret;
4602
4603 wpa_snprintf_hex(pmkid_txt, sizeof(pmkid_txt),
4604 wpa_auth->dot11RSNAPMKIDUsed, PMKID_LEN);
4605
4606 ret = os_snprintf(
4607 buf + len, buflen - len,
4608 "dot11RSNAConfigVersion=%u\n"
4609 "dot11RSNAConfigPairwiseKeysSupported=9999\n"
4610 /* FIX: dot11RSNAConfigGroupCipher */
4611 /* FIX: dot11RSNAConfigGroupRekeyMethod */
4612 /* FIX: dot11RSNAConfigGroupRekeyTime */
4613 /* FIX: dot11RSNAConfigGroupRekeyPackets */
4614 "dot11RSNAConfigGroupRekeyStrict=%u\n"
4615 "dot11RSNAConfigGroupUpdateCount=%u\n"
4616 "dot11RSNAConfigPairwiseUpdateCount=%u\n"
4617 "dot11RSNAConfigGroupCipherSize=%u\n"
4618 "dot11RSNAConfigPMKLifetime=%u\n"
4619 "dot11RSNAConfigPMKReauthThreshold=%u\n"
4620 "dot11RSNAConfigNumberOfPTKSAReplayCounters=0\n"
4621 "dot11RSNAConfigSATimeout=%u\n"
4622 "dot11RSNAAuthenticationSuiteSelected=" RSN_SUITE "\n"
4623 "dot11RSNAPairwiseCipherSelected=" RSN_SUITE "\n"
4624 "dot11RSNAGroupCipherSelected=" RSN_SUITE "\n"
4625 "dot11RSNAPMKIDUsed=%s\n"
4626 "dot11RSNAAuthenticationSuiteRequested=" RSN_SUITE "\n"
4627 "dot11RSNAPairwiseCipherRequested=" RSN_SUITE "\n"
4628 "dot11RSNAGroupCipherRequested=" RSN_SUITE "\n"
4629 "dot11RSNATKIPCounterMeasuresInvoked=%u\n"
4630 "dot11RSNA4WayHandshakeFailures=%u\n"
4631 "dot11RSNAConfigNumberOfGTKSAReplayCounters=0\n",
4632 RSN_VERSION,
Hai Shalomfdcde762020-04-02 11:19:20 -07004633 !!conf->wpa_strict_rekey,
4634 conf->wpa_group_update_count,
4635 conf->wpa_pairwise_update_count,
4636 wpa_cipher_key_len(conf->wpa_group) * 8,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004637 dot11RSNAConfigPMKLifetime,
4638 dot11RSNAConfigPMKReauthThreshold,
4639 dot11RSNAConfigSATimeout,
4640 RSN_SUITE_ARG(wpa_auth->dot11RSNAAuthenticationSuiteSelected),
4641 RSN_SUITE_ARG(wpa_auth->dot11RSNAPairwiseCipherSelected),
4642 RSN_SUITE_ARG(wpa_auth->dot11RSNAGroupCipherSelected),
4643 pmkid_txt,
4644 RSN_SUITE_ARG(wpa_auth->dot11RSNAAuthenticationSuiteRequested),
4645 RSN_SUITE_ARG(wpa_auth->dot11RSNAPairwiseCipherRequested),
4646 RSN_SUITE_ARG(wpa_auth->dot11RSNAGroupCipherRequested),
4647 wpa_auth->dot11RSNATKIPCounterMeasuresInvoked,
4648 wpa_auth->dot11RSNA4WayHandshakeFailures);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004649 if (os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004650 return len;
4651 len += ret;
4652
4653 /* TODO: dot11RSNAConfigPairwiseCiphersTable */
4654 /* TODO: dot11RSNAConfigAuthenticationSuitesTable */
4655
4656 /* Private MIB */
4657 ret = os_snprintf(buf + len, buflen - len, "hostapdWPAGroupState=%d\n",
4658 wpa_auth->group->wpa_group_state);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004659 if (os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004660 return len;
4661 len += ret;
4662
4663 return len;
4664}
4665
4666
4667int wpa_get_mib_sta(struct wpa_state_machine *sm, char *buf, size_t buflen)
4668{
4669 int len = 0, ret;
4670 u32 pairwise = 0;
4671
Hai Shalomfdcde762020-04-02 11:19:20 -07004672 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004673 return 0;
4674
4675 /* TODO: FF-FF-FF-FF-FF-FF entry for broadcast/multicast stats */
4676
4677 /* dot11RSNAStatsEntry */
4678
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07004679 pairwise = wpa_cipher_to_suite(sm->wpa == WPA_VERSION_WPA2 ?
4680 WPA_PROTO_RSN : WPA_PROTO_WPA,
4681 sm->pairwise);
4682 if (pairwise == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004683 return 0;
4684
4685 ret = os_snprintf(
4686 buf + len, buflen - len,
4687 /* TODO: dot11RSNAStatsIndex */
4688 "dot11RSNAStatsSTAAddress=" MACSTR "\n"
4689 "dot11RSNAStatsVersion=1\n"
4690 "dot11RSNAStatsSelectedPairwiseCipher=" RSN_SUITE "\n"
4691 /* TODO: dot11RSNAStatsTKIPICVErrors */
4692 "dot11RSNAStatsTKIPLocalMICFailures=%u\n"
4693 "dot11RSNAStatsTKIPRemoteMICFailures=%u\n"
4694 /* TODO: dot11RSNAStatsCCMPReplays */
4695 /* TODO: dot11RSNAStatsCCMPDecryptErrors */
4696 /* TODO: dot11RSNAStatsTKIPReplays */,
4697 MAC2STR(sm->addr),
4698 RSN_SUITE_ARG(pairwise),
4699 sm->dot11RSNAStatsTKIPLocalMICFailures,
4700 sm->dot11RSNAStatsTKIPRemoteMICFailures);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004701 if (os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004702 return len;
4703 len += ret;
4704
4705 /* Private MIB */
4706 ret = os_snprintf(buf + len, buflen - len,
Hai Shalomc3565922019-10-28 11:58:20 -07004707 "wpa=%d\n"
4708 "AKMSuiteSelector=" RSN_SUITE "\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004709 "hostapdWPAPTKState=%d\n"
4710 "hostapdWPAPTKGroupState=%d\n",
Hai Shalomc3565922019-10-28 11:58:20 -07004711 sm->wpa,
4712 RSN_SUITE_ARG(wpa_akm_to_suite(sm->wpa_key_mgmt)),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004713 sm->wpa_ptk_state,
4714 sm->wpa_ptk_group_state);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004715 if (os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004716 return len;
4717 len += ret;
4718
4719 return len;
4720}
4721
4722
4723void wpa_auth_countermeasures_start(struct wpa_authenticator *wpa_auth)
4724{
4725 if (wpa_auth)
4726 wpa_auth->dot11RSNATKIPCounterMeasuresInvoked++;
4727}
4728
4729
4730int wpa_auth_pairwise_set(struct wpa_state_machine *sm)
4731{
4732 return sm && sm->pairwise_set;
4733}
4734
4735
4736int wpa_auth_get_pairwise(struct wpa_state_machine *sm)
4737{
4738 return sm->pairwise;
4739}
4740
4741
Hai Shalom74f70d42019-02-11 14:42:39 -08004742const u8 * wpa_auth_get_pmk(struct wpa_state_machine *sm, int *len)
4743{
4744 if (!sm)
4745 return NULL;
4746 *len = sm->pmk_len;
4747 return sm->PMK;
4748}
4749
4750
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004751int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm)
4752{
Hai Shalomfdcde762020-04-02 11:19:20 -07004753 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004754 return -1;
4755 return sm->wpa_key_mgmt;
4756}
4757
4758
4759int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm)
4760{
Hai Shalomfdcde762020-04-02 11:19:20 -07004761 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004762 return 0;
4763 return sm->wpa;
4764}
4765
4766
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02004767int wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm)
4768{
4769 if (!sm || !wpa_key_mgmt_ft(sm->wpa_key_mgmt))
4770 return 0;
4771 return sm->tk_already_set;
4772}
4773
4774
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004775int wpa_auth_sta_fils_tk_already_set(struct wpa_state_machine *sm)
4776{
4777 if (!sm || !wpa_key_mgmt_fils(sm->wpa_key_mgmt))
4778 return 0;
4779 return sm->tk_already_set;
4780}
4781
4782
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004783int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm,
4784 struct rsn_pmksa_cache_entry *entry)
4785{
Hai Shalomfdcde762020-04-02 11:19:20 -07004786 if (!sm || sm->pmksa != entry)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004787 return -1;
4788 sm->pmksa = NULL;
4789 return 0;
4790}
4791
4792
4793struct rsn_pmksa_cache_entry *
4794wpa_auth_sta_get_pmksa(struct wpa_state_machine *sm)
4795{
4796 return sm ? sm->pmksa : NULL;
4797}
4798
4799
4800void wpa_auth_sta_local_mic_failure_report(struct wpa_state_machine *sm)
4801{
4802 if (sm)
4803 sm->dot11RSNAStatsTKIPLocalMICFailures++;
4804}
4805
4806
4807const u8 * wpa_auth_get_wpa_ie(struct wpa_authenticator *wpa_auth, size_t *len)
4808{
Hai Shalomfdcde762020-04-02 11:19:20 -07004809 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004810 return NULL;
4811 *len = wpa_auth->wpa_ie_len;
4812 return wpa_auth->wpa_ie;
4813}
4814
4815
4816int wpa_auth_pmksa_add(struct wpa_state_machine *sm, const u8 *pmk,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004817 unsigned int pmk_len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004818 int session_timeout, struct eapol_state_machine *eapol)
4819{
Hai Shalomfdcde762020-04-02 11:19:20 -07004820 if (!sm || sm->wpa != WPA_VERSION_WPA2 ||
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07004821 sm->wpa_auth->conf.disable_pmksa_caching)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004822 return -1;
4823
Hai Shalom81f62d82019-07-22 12:10:00 -07004824#ifdef CONFIG_IEEE80211R_AP
4825 if (pmk_len >= 2 * PMK_LEN && wpa_key_mgmt_ft(sm->wpa_key_mgmt) &&
4826 wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) &&
4827 !wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) {
4828 /* Cache MPMK/XXKey instead of initial part from MSK */
4829 pmk = pmk + PMK_LEN;
4830 pmk_len = PMK_LEN;
4831 } else
4832#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004833 if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004834 if (pmk_len > PMK_LEN_SUITE_B_192)
4835 pmk_len = PMK_LEN_SUITE_B_192;
4836 } else if (pmk_len > PMK_LEN) {
4837 pmk_len = PMK_LEN;
4838 }
4839
Hai Shalom81f62d82019-07-22 12:10:00 -07004840 wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK", pmk, pmk_len);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004841 if (pmksa_cache_auth_add(sm->wpa_auth->pmksa, pmk, pmk_len, NULL,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004842 sm->PTK.kck, sm->PTK.kck_len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004843 sm->wpa_auth->addr, sm->addr, session_timeout,
4844 eapol, sm->wpa_key_mgmt))
4845 return 0;
4846
4847 return -1;
4848}
4849
4850
4851int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth,
4852 const u8 *pmk, size_t len, const u8 *sta_addr,
4853 int session_timeout,
4854 struct eapol_state_machine *eapol)
4855{
Hai Shalomfdcde762020-04-02 11:19:20 -07004856 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004857 return -1;
4858
Hai Shalom81f62d82019-07-22 12:10:00 -07004859 wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK from preauth", pmk, len);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004860 if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, len, NULL,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004861 NULL, 0,
4862 wpa_auth->addr,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004863 sta_addr, session_timeout, eapol,
4864 WPA_KEY_MGMT_IEEE8021X))
4865 return 0;
4866
4867 return -1;
4868}
4869
4870
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004871int wpa_auth_pmksa_add_sae(struct wpa_authenticator *wpa_auth, const u8 *addr,
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004872 const u8 *pmk, const u8 *pmkid)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004873{
4874 if (wpa_auth->conf.disable_pmksa_caching)
4875 return -1;
4876
Hai Shalom81f62d82019-07-22 12:10:00 -07004877 wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK from SAE", pmk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004878 if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, PMK_LEN, pmkid,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004879 NULL, 0,
4880 wpa_auth->addr, addr, 0, NULL,
4881 WPA_KEY_MGMT_SAE))
4882 return 0;
4883
4884 return -1;
4885}
4886
4887
Roshan Pius3a1667e2018-07-03 15:17:14 -07004888void wpa_auth_add_sae_pmkid(struct wpa_state_machine *sm, const u8 *pmkid)
4889{
4890 os_memcpy(sm->pmkid, pmkid, PMKID_LEN);
4891 sm->pmkid_set = 1;
4892}
4893
4894
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004895int wpa_auth_pmksa_add2(struct wpa_authenticator *wpa_auth, const u8 *addr,
4896 const u8 *pmk, size_t pmk_len, const u8 *pmkid,
4897 int session_timeout, int akmp)
4898{
Hai Shaloma20dcd72022-02-04 13:43:00 -08004899 if (!wpa_auth || wpa_auth->conf.disable_pmksa_caching)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004900 return -1;
4901
Hai Shalom81f62d82019-07-22 12:10:00 -07004902 wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK (2)", pmk, PMK_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004903 if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, pmk_len, pmkid,
4904 NULL, 0, wpa_auth->addr, addr, session_timeout,
4905 NULL, akmp))
4906 return 0;
4907
4908 return -1;
4909}
4910
4911
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004912void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth,
4913 const u8 *sta_addr)
4914{
4915 struct rsn_pmksa_cache_entry *pmksa;
4916
Hai Shalomfdcde762020-04-02 11:19:20 -07004917 if (!wpa_auth || !wpa_auth->pmksa)
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004918 return;
4919 pmksa = pmksa_cache_auth_get(wpa_auth->pmksa, sta_addr, NULL);
4920 if (pmksa) {
4921 wpa_printf(MSG_DEBUG, "WPA: Remove PMKSA cache entry for "
4922 MACSTR " based on request", MAC2STR(sta_addr));
4923 pmksa_cache_free_entry(wpa_auth->pmksa, pmksa);
4924 }
4925}
4926
4927
Dmitry Shmidte4663042016-04-04 10:07:49 -07004928int wpa_auth_pmksa_list(struct wpa_authenticator *wpa_auth, char *buf,
4929 size_t len)
4930{
4931 if (!wpa_auth || !wpa_auth->pmksa)
4932 return 0;
4933 return pmksa_cache_auth_list(wpa_auth->pmksa, buf, len);
4934}
4935
4936
4937void wpa_auth_pmksa_flush(struct wpa_authenticator *wpa_auth)
4938{
4939 if (wpa_auth && wpa_auth->pmksa)
4940 pmksa_cache_auth_flush(wpa_auth->pmksa);
4941}
4942
4943
Paul Stewart092955c2017-02-06 09:13:09 -08004944#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
4945#ifdef CONFIG_MESH
4946
4947int wpa_auth_pmksa_list_mesh(struct wpa_authenticator *wpa_auth, const u8 *addr,
4948 char *buf, size_t len)
4949{
4950 if (!wpa_auth || !wpa_auth->pmksa)
4951 return 0;
4952
4953 return pmksa_cache_auth_list_mesh(wpa_auth->pmksa, addr, buf, len);
4954}
4955
4956
4957struct rsn_pmksa_cache_entry *
4958wpa_auth_pmksa_create_entry(const u8 *aa, const u8 *spa, const u8 *pmk,
4959 const u8 *pmkid, int expiration)
4960{
4961 struct rsn_pmksa_cache_entry *entry;
4962 struct os_reltime now;
4963
4964 entry = pmksa_cache_auth_create_entry(pmk, PMK_LEN, pmkid, NULL, 0, aa,
4965 spa, 0, NULL, WPA_KEY_MGMT_SAE);
4966 if (!entry)
4967 return NULL;
4968
4969 os_get_reltime(&now);
4970 entry->expiration = now.sec + expiration;
4971 return entry;
4972}
4973
4974
4975int wpa_auth_pmksa_add_entry(struct wpa_authenticator *wpa_auth,
4976 struct rsn_pmksa_cache_entry *entry)
4977{
4978 int ret;
4979
4980 if (!wpa_auth || !wpa_auth->pmksa)
4981 return -1;
4982
4983 ret = pmksa_cache_auth_add_entry(wpa_auth->pmksa, entry);
4984 if (ret < 0)
4985 wpa_printf(MSG_DEBUG,
4986 "RSN: Failed to store external PMKSA cache for "
4987 MACSTR, MAC2STR(entry->spa));
4988
4989 return ret;
4990}
4991
4992#endif /* CONFIG_MESH */
4993#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
4994
4995
Dmitry Shmidte4663042016-04-04 10:07:49 -07004996struct rsn_pmksa_cache_entry *
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004997wpa_auth_pmksa_get(struct wpa_authenticator *wpa_auth, const u8 *sta_addr,
4998 const u8 *pmkid)
Dmitry Shmidte4663042016-04-04 10:07:49 -07004999{
5000 if (!wpa_auth || !wpa_auth->pmksa)
5001 return NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005002 return pmksa_cache_auth_get(wpa_auth->pmksa, sta_addr, pmkid);
Dmitry Shmidte4663042016-04-04 10:07:49 -07005003}
5004
5005
5006void wpa_auth_pmksa_set_to_sm(struct rsn_pmksa_cache_entry *pmksa,
5007 struct wpa_state_machine *sm,
5008 struct wpa_authenticator *wpa_auth,
5009 u8 *pmkid, u8 *pmk)
5010{
5011 if (!sm)
5012 return;
5013
5014 sm->pmksa = pmksa;
5015 os_memcpy(pmk, pmksa->pmk, PMK_LEN);
5016 os_memcpy(pmkid, pmksa->pmkid, PMKID_LEN);
5017 os_memcpy(wpa_auth->dot11RSNAPMKIDUsed, pmksa->pmkid, PMKID_LEN);
5018}
5019
5020
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005021/*
5022 * Remove and free the group from wpa_authenticator. This is triggered by a
5023 * callback to make sure nobody is currently iterating the group list while it
5024 * gets modified.
5025 */
5026static void wpa_group_free(struct wpa_authenticator *wpa_auth,
5027 struct wpa_group *group)
5028{
5029 struct wpa_group *prev = wpa_auth->group;
5030
5031 wpa_printf(MSG_DEBUG, "WPA: Remove group state machine for VLAN-ID %d",
5032 group->vlan_id);
5033
5034 while (prev) {
5035 if (prev->next == group) {
5036 /* This never frees the special first group as needed */
5037 prev->next = group->next;
5038 os_free(group);
5039 break;
5040 }
5041 prev = prev->next;
5042 }
5043
5044}
5045
5046
5047/* Increase the reference counter for group */
5048static void wpa_group_get(struct wpa_authenticator *wpa_auth,
5049 struct wpa_group *group)
5050{
5051 /* Skip the special first group */
5052 if (wpa_auth->group == group)
5053 return;
5054
5055 group->references++;
5056}
5057
5058
5059/* Decrease the reference counter and maybe free the group */
5060static void wpa_group_put(struct wpa_authenticator *wpa_auth,
5061 struct wpa_group *group)
5062{
5063 /* Skip the special first group */
5064 if (wpa_auth->group == group)
5065 return;
5066
5067 group->references--;
5068 if (group->references)
5069 return;
5070 wpa_group_free(wpa_auth, group);
5071}
5072
5073
5074/*
5075 * Add a group that has its references counter set to zero. Caller needs to
5076 * call wpa_group_get() on the return value to mark the entry in use.
5077 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005078static struct wpa_group *
5079wpa_auth_add_group(struct wpa_authenticator *wpa_auth, int vlan_id)
5080{
5081 struct wpa_group *group;
5082
Hai Shalomfdcde762020-04-02 11:19:20 -07005083 if (!wpa_auth || !wpa_auth->group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005084 return NULL;
5085
5086 wpa_printf(MSG_DEBUG, "WPA: Add group state machine for VLAN-ID %d",
5087 vlan_id);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005088 group = wpa_group_init(wpa_auth, vlan_id, 0);
Hai Shalomfdcde762020-04-02 11:19:20 -07005089 if (!group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005090 return NULL;
5091
5092 group->next = wpa_auth->group->next;
5093 wpa_auth->group->next = group;
5094
5095 return group;
5096}
5097
5098
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005099/*
5100 * Enforce that the group state machine for the VLAN is running, increase
5101 * reference counter as interface is up. References might have been increased
5102 * even if a negative value is returned.
5103 * Returns: -1 on error (group missing, group already failed); otherwise, 0
5104 */
5105int wpa_auth_ensure_group(struct wpa_authenticator *wpa_auth, int vlan_id)
5106{
5107 struct wpa_group *group;
5108
Hai Shalomfdcde762020-04-02 11:19:20 -07005109 if (!wpa_auth)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005110 return 0;
5111
5112 group = wpa_auth->group;
5113 while (group) {
5114 if (group->vlan_id == vlan_id)
5115 break;
5116 group = group->next;
5117 }
5118
Hai Shalomfdcde762020-04-02 11:19:20 -07005119 if (!group) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005120 group = wpa_auth_add_group(wpa_auth, vlan_id);
Hai Shalomfdcde762020-04-02 11:19:20 -07005121 if (!group)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005122 return -1;
5123 }
5124
5125 wpa_printf(MSG_DEBUG,
5126 "WPA: Ensure group state machine running for VLAN ID %d",
5127 vlan_id);
5128
5129 wpa_group_get(wpa_auth, group);
5130 group->num_setup_iface++;
5131
5132 if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
5133 return -1;
5134
5135 return 0;
5136}
5137
5138
5139/*
5140 * Decrease reference counter, expected to be zero afterwards.
5141 * returns: -1 on error (group not found, group in fail state)
5142 * -2 if wpa_group is still referenced
5143 * 0 else
5144 */
5145int wpa_auth_release_group(struct wpa_authenticator *wpa_auth, int vlan_id)
5146{
5147 struct wpa_group *group;
5148 int ret = 0;
5149
Hai Shalomfdcde762020-04-02 11:19:20 -07005150 if (!wpa_auth)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005151 return 0;
5152
5153 group = wpa_auth->group;
5154 while (group) {
5155 if (group->vlan_id == vlan_id)
5156 break;
5157 group = group->next;
5158 }
5159
Hai Shalomfdcde762020-04-02 11:19:20 -07005160 if (!group)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005161 return -1;
5162
5163 wpa_printf(MSG_DEBUG,
5164 "WPA: Try stopping group state machine for VLAN ID %d",
5165 vlan_id);
5166
5167 if (group->num_setup_iface <= 0) {
5168 wpa_printf(MSG_ERROR,
5169 "WPA: wpa_auth_release_group called more often than wpa_auth_ensure_group for VLAN ID %d, skipping.",
5170 vlan_id);
5171 return -1;
5172 }
5173 group->num_setup_iface--;
5174
5175 if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
5176 ret = -1;
5177
5178 if (group->references > 1) {
5179 wpa_printf(MSG_DEBUG,
5180 "WPA: Cannot stop group state machine for VLAN ID %d as references are still hold",
5181 vlan_id);
5182 ret = -2;
5183 }
5184
5185 wpa_group_put(wpa_auth, group);
5186
5187 return ret;
5188}
5189
5190
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005191int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id)
5192{
5193 struct wpa_group *group;
5194
Hai Shalomfdcde762020-04-02 11:19:20 -07005195 if (!sm || !sm->wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005196 return 0;
5197
5198 group = sm->wpa_auth->group;
5199 while (group) {
5200 if (group->vlan_id == vlan_id)
5201 break;
5202 group = group->next;
5203 }
5204
Hai Shalomfdcde762020-04-02 11:19:20 -07005205 if (!group) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005206 group = wpa_auth_add_group(sm->wpa_auth, vlan_id);
Hai Shalomfdcde762020-04-02 11:19:20 -07005207 if (!group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005208 return -1;
5209 }
5210
5211 if (sm->group == group)
5212 return 0;
5213
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005214 if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
5215 return -1;
5216
Hai Shalomfdcde762020-04-02 11:19:20 -07005217 wpa_printf(MSG_DEBUG, "WPA: Moving STA " MACSTR
5218 " to use group state machine for VLAN ID %d",
5219 MAC2STR(sm->addr), vlan_id);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005220
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005221 wpa_group_get(sm->wpa_auth, group);
5222 wpa_group_put(sm->wpa_auth, sm->group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005223 sm->group = group;
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005224
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005225 return 0;
5226}
5227
5228
5229void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth,
5230 struct wpa_state_machine *sm, int ack)
5231{
Hai Shalomfdcde762020-04-02 11:19:20 -07005232 if (!wpa_auth || !sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005233 return;
5234 wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key TX status for STA " MACSTR
5235 " ack=%d", MAC2STR(sm->addr), ack);
5236 if (sm->pending_1_of_4_timeout && ack) {
5237 /*
5238 * Some deployed supplicant implementations update their SNonce
5239 * for each EAPOL-Key 2/4 message even within the same 4-way
5240 * handshake and then fail to use the first SNonce when
5241 * deriving the PTK. This results in unsuccessful 4-way
5242 * handshake whenever the relatively short initial timeout is
5243 * reached and EAPOL-Key 1/4 is retransmitted. Try to work
5244 * around this by increasing the timeout now that we know that
5245 * the station has received the frame.
5246 */
5247 int timeout_ms = eapol_key_timeout_subseq;
Hai Shalomfdcde762020-04-02 11:19:20 -07005248 wpa_printf(MSG_DEBUG,
5249 "WPA: Increase initial EAPOL-Key 1/4 timeout by %u ms because of acknowledged frame",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005250 timeout_ms);
5251 eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm);
5252 eloop_register_timeout(timeout_ms / 1000,
5253 (timeout_ms % 1000) * 1000,
5254 wpa_send_eapol_timeout, wpa_auth, sm);
5255 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005256
5257#ifdef CONFIG_TESTING_OPTIONS
5258 if (sm->eapol_status_cb) {
5259 sm->eapol_status_cb(sm->eapol_status_cb_ctx1,
5260 sm->eapol_status_cb_ctx2);
5261 sm->eapol_status_cb = NULL;
5262 }
5263#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005264}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005265
5266
5267int wpa_auth_uses_sae(struct wpa_state_machine *sm)
5268{
Hai Shalomfdcde762020-04-02 11:19:20 -07005269 if (!sm)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005270 return 0;
5271 return wpa_key_mgmt_sae(sm->wpa_key_mgmt);
5272}
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005273
5274
5275int wpa_auth_uses_ft_sae(struct wpa_state_machine *sm)
5276{
Hai Shalomfdcde762020-04-02 11:19:20 -07005277 if (!sm)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005278 return 0;
5279 return sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_SAE;
5280}
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08005281
5282
5283#ifdef CONFIG_P2P
5284int wpa_auth_get_ip_addr(struct wpa_state_machine *sm, u8 *addr)
5285{
Hai Shalomfdcde762020-04-02 11:19:20 -07005286 if (!sm || WPA_GET_BE32(sm->ip_addr) == 0)
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08005287 return -1;
5288 os_memcpy(addr, sm->ip_addr, 4);
5289 return 0;
5290}
5291#endif /* CONFIG_P2P */
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08005292
5293
5294int wpa_auth_radius_das_disconnect_pmksa(struct wpa_authenticator *wpa_auth,
5295 struct radius_das_attrs *attr)
5296{
5297 return pmksa_cache_auth_radius_das_disconnect(wpa_auth->pmksa, attr);
5298}
Dmitry Shmidt7f656022015-02-25 14:36:37 -08005299
5300
5301void wpa_auth_reconfig_group_keys(struct wpa_authenticator *wpa_auth)
5302{
5303 struct wpa_group *group;
5304
5305 if (!wpa_auth)
5306 return;
5307 for (group = wpa_auth->group; group; group = group->next)
5308 wpa_group_config_group_keys(wpa_auth, group);
5309}
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005310
5311
5312#ifdef CONFIG_FILS
5313
5314struct wpa_auth_fils_iter_data {
5315 struct wpa_authenticator *auth;
5316 const u8 *cache_id;
5317 struct rsn_pmksa_cache_entry *pmksa;
5318 const u8 *spa;
5319 const u8 *pmkid;
5320};
5321
5322
5323static int wpa_auth_fils_iter(struct wpa_authenticator *a, void *ctx)
5324{
5325 struct wpa_auth_fils_iter_data *data = ctx;
5326
5327 if (a == data->auth || !a->conf.fils_cache_id_set ||
5328 os_memcmp(a->conf.fils_cache_id, data->cache_id,
5329 FILS_CACHE_ID_LEN) != 0)
5330 return 0;
5331 data->pmksa = pmksa_cache_auth_get(a->pmksa, data->spa, data->pmkid);
5332 return data->pmksa != NULL;
5333}
5334
5335
5336struct rsn_pmksa_cache_entry *
5337wpa_auth_pmksa_get_fils_cache_id(struct wpa_authenticator *wpa_auth,
5338 const u8 *sta_addr, const u8 *pmkid)
5339{
5340 struct wpa_auth_fils_iter_data idata;
5341
5342 if (!wpa_auth->conf.fils_cache_id_set)
5343 return NULL;
5344 idata.auth = wpa_auth;
5345 idata.cache_id = wpa_auth->conf.fils_cache_id;
5346 idata.pmksa = NULL;
5347 idata.spa = sta_addr;
5348 idata.pmkid = pmkid;
5349 wpa_auth_for_each_auth(wpa_auth, wpa_auth_fils_iter, &idata);
5350 return idata.pmksa;
5351}
5352
5353
5354#ifdef CONFIG_IEEE80211R_AP
Roshan Pius3a1667e2018-07-03 15:17:14 -07005355int wpa_auth_write_fte(struct wpa_authenticator *wpa_auth, int use_sha384,
5356 u8 *buf, size_t len)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005357{
5358 struct wpa_auth_config *conf = &wpa_auth->conf;
5359
Roshan Pius3a1667e2018-07-03 15:17:14 -07005360 return wpa_write_ftie(conf, use_sha384, conf->r0_key_holder,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005361 conf->r0_key_holder_len,
Hai Shalomfdcde762020-04-02 11:19:20 -07005362 NULL, NULL, buf, len, NULL, 0, 0);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005363}
5364#endif /* CONFIG_IEEE80211R_AP */
5365
5366
5367void wpa_auth_get_fils_aead_params(struct wpa_state_machine *sm,
5368 u8 *fils_anonce, u8 *fils_snonce,
5369 u8 *fils_kek, size_t *fils_kek_len)
5370{
5371 os_memcpy(fils_anonce, sm->ANonce, WPA_NONCE_LEN);
5372 os_memcpy(fils_snonce, sm->SNonce, WPA_NONCE_LEN);
5373 os_memcpy(fils_kek, sm->PTK.kek, WPA_KEK_MAX_LEN);
5374 *fils_kek_len = sm->PTK.kek_len;
5375}
5376
Hai Shalom81f62d82019-07-22 12:10:00 -07005377
5378void wpa_auth_add_fils_pmk_pmkid(struct wpa_state_machine *sm, const u8 *pmk,
5379 size_t pmk_len, const u8 *pmkid)
5380{
5381 os_memcpy(sm->PMK, pmk, pmk_len);
5382 sm->pmk_len = pmk_len;
5383 os_memcpy(sm->pmkid, pmkid, PMKID_LEN);
5384 sm->pmkid_set = 1;
5385}
5386
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005387#endif /* CONFIG_FILS */
5388
5389
Hai Shalom021b0b52019-04-10 11:17:58 -07005390void wpa_auth_set_auth_alg(struct wpa_state_machine *sm, u16 auth_alg)
5391{
5392 if (sm)
5393 sm->auth_alg = auth_alg;
5394}
5395
5396
5397#ifdef CONFIG_DPP2
5398void wpa_auth_set_dpp_z(struct wpa_state_machine *sm, const struct wpabuf *z)
5399{
5400 if (sm) {
5401 wpabuf_clear_free(sm->dpp_z);
5402 sm->dpp_z = z ? wpabuf_dup(z) : NULL;
5403 }
5404}
5405#endif /* CONFIG_DPP2 */
5406
5407
Hai Shalom899fcc72020-10-19 14:38:18 -07005408void wpa_auth_set_transition_disable(struct wpa_authenticator *wpa_auth,
5409 u8 val)
5410{
5411 if (wpa_auth)
5412 wpa_auth->conf.transition_disable = val;
5413}
5414
5415
Roshan Pius3a1667e2018-07-03 15:17:14 -07005416#ifdef CONFIG_TESTING_OPTIONS
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005417
5418int wpa_auth_resend_m1(struct wpa_state_machine *sm, int change_anonce,
5419 void (*cb)(void *ctx1, void *ctx2),
5420 void *ctx1, void *ctx2)
5421{
5422 const u8 *anonce = sm->ANonce;
5423 u8 anonce_buf[WPA_NONCE_LEN];
5424
5425 if (change_anonce) {
5426 if (random_get_bytes(anonce_buf, WPA_NONCE_LEN))
5427 return -1;
5428 anonce = anonce_buf;
5429 }
5430
5431 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
5432 "sending 1/4 msg of 4-Way Handshake (TESTING)");
5433 wpa_send_eapol(sm->wpa_auth, sm,
5434 WPA_KEY_INFO_ACK | WPA_KEY_INFO_KEY_TYPE, NULL,
5435 anonce, NULL, 0, 0, 0);
5436 return 0;
5437}
5438
5439
5440int wpa_auth_resend_m3(struct wpa_state_machine *sm,
5441 void (*cb)(void *ctx1, void *ctx2),
5442 void *ctx1, void *ctx2)
5443{
Roshan Pius3a1667e2018-07-03 15:17:14 -07005444 u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde, *pos;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005445 u8 *opos;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005446 size_t gtk_len, kde_len;
Hai Shalom899fcc72020-10-19 14:38:18 -07005447 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005448 struct wpa_group *gsm = sm->group;
5449 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07005450 int wpa_ie_len, secure, gtkidx, encr = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07005451 u8 hdr[2];
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005452
5453 /* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, [MDIE],
Hai Shalomfdcde762020-04-02 11:19:20 -07005454 GTK[GN], IGTK, [BIGTK], [FTIE], [TIE * 2])
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005455 */
5456
5457 /* Use 0 RSC */
5458 os_memset(rsc, 0, WPA_KEY_RSC_LEN);
5459 /* If FT is used, wpa_auth->wpa_ie includes both RSNIE and MDIE */
5460 wpa_ie = sm->wpa_auth->wpa_ie;
5461 wpa_ie_len = sm->wpa_auth->wpa_ie_len;
5462 if (sm->wpa == WPA_VERSION_WPA &&
5463 (sm->wpa_auth->conf.wpa & WPA_PROTO_RSN) &&
5464 wpa_ie_len > wpa_ie[1] + 2 && wpa_ie[0] == WLAN_EID_RSN) {
5465 /* WPA-only STA, remove RSN IE and possible MDIE */
5466 wpa_ie = wpa_ie + wpa_ie[1] + 2;
Hai Shalom60840252021-02-19 19:02:11 -08005467 if (wpa_ie[0] == WLAN_EID_RSNX)
5468 wpa_ie = wpa_ie + wpa_ie[1] + 2;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005469 if (wpa_ie[0] == WLAN_EID_MOBILITY_DOMAIN)
5470 wpa_ie = wpa_ie + wpa_ie[1] + 2;
5471 wpa_ie_len = wpa_ie[1] + 2;
5472 }
5473 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
5474 "sending 3/4 msg of 4-Way Handshake (TESTING)");
5475 if (sm->wpa == WPA_VERSION_WPA2) {
5476 /* WPA2 send GTK in the 4-way handshake */
5477 secure = 1;
5478 gtk = gsm->GTK[gsm->GN - 1];
5479 gtk_len = gsm->GTK_len;
Hai Shalomc3565922019-10-28 11:58:20 -07005480 gtkidx = gsm->GN;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005481 _rsc = rsc;
5482 encr = 1;
5483 } else {
5484 /* WPA does not include GTK in msg 3/4 */
5485 secure = 0;
5486 gtk = NULL;
5487 gtk_len = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005488 _rsc = NULL;
5489 if (sm->rx_eapol_key_secure) {
5490 /*
5491 * It looks like Windows 7 supplicant tries to use
5492 * Secure bit in msg 2/4 after having reported Michael
5493 * MIC failure and it then rejects the 4-way handshake
5494 * if msg 3/4 does not set Secure bit. Work around this
5495 * by setting the Secure bit here even in the case of
5496 * WPA if the supplicant used it first.
5497 */
5498 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07005499 "STA used Secure bit in WPA msg 2/4 - set Secure for 3/4 as workaround");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005500 secure = 1;
5501 }
5502 }
5503
Hai Shalom74f70d42019-02-11 14:42:39 -08005504 kde_len = wpa_ie_len + ieee80211w_kde_len(sm) + ocv_oci_len(sm);
Hai Shalomfdcde762020-04-02 11:19:20 -07005505
5506 if (sm->use_ext_key_id)
5507 kde_len += 2 + RSN_SELECTOR_LEN + 2;
5508
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005509 if (gtk)
5510 kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len;
5511#ifdef CONFIG_IEEE80211R_AP
5512 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
5513 kde_len += 2 + PMKID_LEN; /* PMKR1Name into RSN IE */
5514 kde_len += 300; /* FTIE + 2 * TIE */
5515 }
5516#endif /* CONFIG_IEEE80211R_AP */
5517 kde = os_malloc(kde_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07005518 if (!kde)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005519 return -1;
5520
5521 pos = kde;
5522 os_memcpy(pos, wpa_ie, wpa_ie_len);
5523 pos += wpa_ie_len;
5524#ifdef CONFIG_IEEE80211R_AP
5525 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
5526 int res;
5527 size_t elen;
5528
5529 elen = pos - kde;
5530 res = wpa_insert_pmkid(kde, &elen, sm->pmk_r1_name);
5531 if (res < 0) {
Hai Shalomfdcde762020-04-02 11:19:20 -07005532 wpa_printf(MSG_ERROR,
5533 "FT: Failed to insert PMKR1Name into RSN IE in EAPOL-Key data");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005534 os_free(kde);
5535 return -1;
5536 }
5537 pos -= wpa_ie_len;
5538 pos += elen;
5539 }
5540#endif /* CONFIG_IEEE80211R_AP */
Hai Shalomfdcde762020-04-02 11:19:20 -07005541 hdr[1] = 0;
5542
5543 if (sm->use_ext_key_id) {
5544 hdr[0] = sm->keyidx_active & 0x01;
5545 pos = wpa_add_kde(pos, RSN_KEY_DATA_KEYID, hdr, 2, NULL, 0);
5546 }
5547
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005548 if (gtk) {
Hai Shalomc3565922019-10-28 11:58:20 -07005549 hdr[0] = gtkidx & 0x03;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005550 pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
5551 gtk, gtk_len);
5552 }
5553 opos = pos;
5554 pos = ieee80211w_kde_add(sm, pos);
Roshan Pius3a1667e2018-07-03 15:17:14 -07005555 if (pos - opos >= 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN) {
5556 /* skip KDE header and keyid */
5557 opos += 2 + RSN_SELECTOR_LEN + 2;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005558 os_memset(opos, 0, 6); /* clear PN */
5559 }
Hai Shalom899fcc72020-10-19 14:38:18 -07005560 if (ocv_oci_add(sm, &pos, conf->oci_freq_override_eapol_m3) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -08005561 os_free(kde);
5562 return -1;
5563 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005564
5565#ifdef CONFIG_IEEE80211R_AP
5566 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
5567 int res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005568
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005569 if (sm->assoc_resp_ftie &&
5570 kde + kde_len - pos >= 2 + sm->assoc_resp_ftie[1]) {
5571 os_memcpy(pos, sm->assoc_resp_ftie,
5572 2 + sm->assoc_resp_ftie[1]);
5573 res = 2 + sm->assoc_resp_ftie[1];
5574 } else {
Roshan Pius3a1667e2018-07-03 15:17:14 -07005575 int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt);
5576
5577 res = wpa_write_ftie(conf, use_sha384,
5578 conf->r0_key_holder,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005579 conf->r0_key_holder_len,
5580 NULL, NULL, pos,
5581 kde + kde_len - pos,
Hai Shalomfdcde762020-04-02 11:19:20 -07005582 NULL, 0, 0);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005583 }
5584 if (res < 0) {
Hai Shalomfdcde762020-04-02 11:19:20 -07005585 wpa_printf(MSG_ERROR,
5586 "FT: Failed to insert FTIE into EAPOL-Key Key Data");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005587 os_free(kde);
5588 return -1;
5589 }
5590 pos += res;
5591
5592 /* TIE[ReassociationDeadline] (TU) */
5593 *pos++ = WLAN_EID_TIMEOUT_INTERVAL;
5594 *pos++ = 5;
5595 *pos++ = WLAN_TIMEOUT_REASSOC_DEADLINE;
5596 WPA_PUT_LE32(pos, conf->reassociation_deadline);
5597 pos += 4;
5598
5599 /* TIE[KeyLifetime] (seconds) */
5600 *pos++ = WLAN_EID_TIMEOUT_INTERVAL;
5601 *pos++ = 5;
5602 *pos++ = WLAN_TIMEOUT_KEY_LIFETIME;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005603 WPA_PUT_LE32(pos, conf->r0_key_lifetime);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005604 pos += 4;
5605 }
5606#endif /* CONFIG_IEEE80211R_AP */
5607
5608 wpa_send_eapol(sm->wpa_auth, sm,
5609 (secure ? WPA_KEY_INFO_SECURE : 0) |
5610 (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
5611 WPA_KEY_INFO_MIC : 0) |
5612 WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL |
5613 WPA_KEY_INFO_KEY_TYPE,
Hai Shalomc3565922019-10-28 11:58:20 -07005614 _rsc, sm->ANonce, kde, pos - kde, 0, encr);
Sunil Ravia04bd252022-05-02 22:54:18 -07005615 bin_clear_free(kde, kde_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005616 return 0;
5617}
5618
5619
5620int wpa_auth_resend_group_m1(struct wpa_state_machine *sm,
5621 void (*cb)(void *ctx1, void *ctx2),
5622 void *ctx1, void *ctx2)
5623{
5624 u8 rsc[WPA_KEY_RSC_LEN];
Hai Shalom899fcc72020-10-19 14:38:18 -07005625 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005626 struct wpa_group *gsm = sm->group;
5627 const u8 *kde;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005628 u8 *kde_buf = NULL, *pos, hdr[2];
Roshan Pius3a1667e2018-07-03 15:17:14 -07005629 u8 *opos;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005630 size_t kde_len;
5631 u8 *gtk;
5632
5633 /* Send EAPOL(1, 1, 1, !Pair, G, RSC, GNonce, MIC(PTK), GTK[GN]) */
5634 os_memset(rsc, 0, WPA_KEY_RSC_LEN);
5635 /* Use 0 RSC */
5636 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
5637 "sending 1/2 msg of Group Key Handshake (TESTING)");
5638
5639 gtk = gsm->GTK[gsm->GN - 1];
5640 if (sm->wpa == WPA_VERSION_WPA2) {
5641 kde_len = 2 + RSN_SELECTOR_LEN + 2 + gsm->GTK_len +
Hai Shalom74f70d42019-02-11 14:42:39 -08005642 ieee80211w_kde_len(sm) + ocv_oci_len(sm);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005643 kde_buf = os_malloc(kde_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07005644 if (!kde_buf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005645 return -1;
5646
5647 kde = pos = kde_buf;
5648 hdr[0] = gsm->GN & 0x03;
5649 hdr[1] = 0;
5650 pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
5651 gtk, gsm->GTK_len);
5652 opos = pos;
5653 pos = ieee80211w_kde_add(sm, pos);
Roshan Pius3a1667e2018-07-03 15:17:14 -07005654 if (pos - opos >=
5655 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN) {
5656 /* skip KDE header and keyid */
5657 opos += 2 + RSN_SELECTOR_LEN + 2;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005658 os_memset(opos, 0, 6); /* clear PN */
5659 }
Hai Shalom899fcc72020-10-19 14:38:18 -07005660 if (ocv_oci_add(sm, &pos,
5661 conf->oci_freq_override_eapol_g1) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -08005662 os_free(kde_buf);
5663 return -1;
5664 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005665 kde_len = pos - kde;
5666 } else {
5667 kde = gtk;
5668 kde_len = gsm->GTK_len;
5669 }
5670
5671 sm->eapol_status_cb = cb;
5672 sm->eapol_status_cb_ctx1 = ctx1;
5673 sm->eapol_status_cb_ctx2 = ctx2;
5674
5675 wpa_send_eapol(sm->wpa_auth, sm,
5676 WPA_KEY_INFO_SECURE |
5677 (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
5678 WPA_KEY_INFO_MIC : 0) |
5679 WPA_KEY_INFO_ACK |
5680 (!sm->Pair ? WPA_KEY_INFO_INSTALL : 0),
5681 rsc, NULL, kde, kde_len, gsm->GN, 1);
5682
Sunil Ravia04bd252022-05-02 22:54:18 -07005683 bin_clear_free(kde_buf, kde_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005684 return 0;
5685}
5686
Roshan Pius3a1667e2018-07-03 15:17:14 -07005687
5688int wpa_auth_rekey_gtk(struct wpa_authenticator *wpa_auth)
5689{
5690 if (!wpa_auth)
5691 return -1;
5692 eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL);
5693 return eloop_register_timeout(0, 0, wpa_rekey_gtk, wpa_auth, NULL);
5694}
5695
Hai Shalomb755a2a2020-04-23 21:49:02 -07005696
Hai Shaloma20dcd72022-02-04 13:43:00 -08005697int wpa_auth_rekey_ptk(struct wpa_authenticator *wpa_auth,
5698 struct wpa_state_machine *sm)
5699{
5700 if (!wpa_auth || !sm)
5701 return -1;
5702 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "rekeying PTK");
5703 wpa_request_new_ptk(sm);
5704 wpa_sm_step(sm);
5705 return 0;
5706}
5707
5708
Hai Shalomb755a2a2020-04-23 21:49:02 -07005709void wpa_auth_set_ft_rsnxe_used(struct wpa_authenticator *wpa_auth, int val)
5710{
5711 if (wpa_auth)
5712 wpa_auth->conf.ft_rsnxe_used = val;
5713}
5714
Hai Shalom899fcc72020-10-19 14:38:18 -07005715
5716void wpa_auth_set_ocv_override_freq(struct wpa_authenticator *wpa_auth,
5717 enum wpa_auth_ocv_override_frame frame,
5718 unsigned int freq)
5719{
5720 if (!wpa_auth)
5721 return;
5722 switch (frame) {
5723 case WPA_AUTH_OCV_OVERRIDE_EAPOL_M3:
5724 wpa_auth->conf.oci_freq_override_eapol_m3 = freq;
5725 break;
5726 case WPA_AUTH_OCV_OVERRIDE_EAPOL_G1:
5727 wpa_auth->conf.oci_freq_override_eapol_g1 = freq;
5728 break;
5729 case WPA_AUTH_OCV_OVERRIDE_FT_ASSOC:
5730 wpa_auth->conf.oci_freq_override_ft_assoc = freq;
5731 break;
5732 case WPA_AUTH_OCV_OVERRIDE_FILS_ASSOC:
5733 wpa_auth->conf.oci_freq_override_fils_assoc = freq;
5734 break;
5735 }
5736}
5737
Kai Shie75b0652020-11-24 20:31:29 -08005738void wpa_auth_set_skip_send_eapol(struct wpa_authenticator *wpa_auth,
5739 u8 val)
5740{
5741 if (wpa_auth)
5742 wpa_auth->conf.skip_send_eapol = val;
5743}
5744
5745void wpa_auth_set_enable_eapol_large_timeout(struct wpa_authenticator *wpa_auth,
5746 u8 val)
5747{
5748 if (wpa_auth)
5749 wpa_auth->conf.enable_eapol_large_timeout = val;
5750}
5751
5752
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005753#endif /* CONFIG_TESTING_OPTIONS */
Sunil Ravia04bd252022-05-02 22:54:18 -07005754
5755
5756void wpa_auth_sta_radius_psk_resp(struct wpa_state_machine *sm, bool success)
5757{
5758 if (!sm->waiting_radius_psk) {
5759 wpa_printf(MSG_DEBUG,
5760 "Ignore RADIUS PSK response for " MACSTR
5761 " that did not wait one",
5762 MAC2STR(sm->addr));
5763 return;
5764 }
5765
5766 wpa_printf(MSG_DEBUG, "RADIUS PSK response for " MACSTR " (%s)",
5767 MAC2STR(sm->addr), success ? "success" : "fail");
5768 sm->waiting_radius_psk = 0;
5769
5770 if (success) {
5771 /* Try to process the EAPOL-Key msg 2/4 again */
5772 sm->EAPOLKeyReceived = true;
5773 } else {
5774 sm->Disconnect = true;
5775 }
5776
5777 eloop_register_timeout(0, 0, wpa_sm_call_step, sm, NULL);
5778}