blob: ad918839c6de609dbc5f9e1cb0095fc6c83731fc [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)) {
738 u32 start;
Hai Shalomfdcde762020-04-02 11:19:20 -0700739 wpa_printf(MSG_DEBUG,
740 "P2P: Free assigned IP address %u.%u.%u.%u from "
741 MACSTR,
Dmitry Shmidtcf32e602014-01-28 10:57:39 -0800742 sm->ip_addr[0], sm->ip_addr[1],
743 sm->ip_addr[2], sm->ip_addr[3],
744 MAC2STR(sm->addr));
745 start = WPA_GET_BE32(sm->wpa_auth->conf.ip_addr_start);
746 bitfield_clear(sm->wpa_auth->ip_pool,
747 WPA_GET_BE32(sm->ip_addr) - start);
748 }
749#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700750 if (sm->GUpdateStationKeys) {
751 sm->group->GKeyDoneStations--;
Hai Shalome21d4e82020-04-29 16:34:06 -0700752 sm->GUpdateStationKeys = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700753 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800754#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700755 os_free(sm->assoc_resp_ftie);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700756 wpabuf_free(sm->ft_pending_req_ies);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800757#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700758 os_free(sm->last_rx_eapol_key);
759 os_free(sm->wpa_ie);
Hai Shalomc3565922019-10-28 11:58:20 -0700760 os_free(sm->rsnxe);
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700761 wpa_group_put(sm->wpa_auth, sm->group);
Hai Shalom021b0b52019-04-10 11:17:58 -0700762#ifdef CONFIG_DPP2
763 wpabuf_clear_free(sm->dpp_z);
764#endif /* CONFIG_DPP2 */
Hai Shalom1dc4d202019-04-29 16:22:27 -0700765 bin_clear_free(sm, sizeof(*sm));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700766}
767
768
769void wpa_auth_sta_deinit(struct wpa_state_machine *sm)
770{
Hai Shalomfdcde762020-04-02 11:19:20 -0700771 struct wpa_authenticator *wpa_auth;
772
773 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700774 return;
775
Hai Shalomfdcde762020-04-02 11:19:20 -0700776 wpa_auth = sm->wpa_auth;
777 if (wpa_auth->conf.wpa_strict_rekey && sm->has_GTK) {
778 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
779 "strict rekeying - force GTK rekey since STA is leaving");
Roshan Pius3a1667e2018-07-03 15:17:14 -0700780 if (eloop_deplete_timeout(0, 500000, wpa_rekey_gtk,
Hai Shalomfdcde762020-04-02 11:19:20 -0700781 wpa_auth, NULL) == -1)
782 eloop_register_timeout(0, 500000, wpa_rekey_gtk,
783 wpa_auth, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700784 }
785
Hai Shalomfdcde762020-04-02 11:19:20 -0700786 eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700787 sm->pending_1_of_4_timeout = 0;
788 eloop_cancel_timeout(wpa_sm_call_step, sm, NULL);
Hai Shalomfdcde762020-04-02 11:19:20 -0700789 eloop_cancel_timeout(wpa_rekey_ptk, wpa_auth, sm);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700790#ifdef CONFIG_IEEE80211R_AP
791 wpa_ft_sta_deinit(sm);
792#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700793 if (sm->in_step_loop) {
794 /* Must not free state machine while wpa_sm_step() is running.
795 * Freeing will be completed in the end of wpa_sm_step(). */
Hai Shalomfdcde762020-04-02 11:19:20 -0700796 wpa_printf(MSG_DEBUG,
797 "WPA: Registering pending STA state machine deinit for "
798 MACSTR, MAC2STR(sm->addr));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700799 sm->pending_deinit = 1;
800 } else
801 wpa_free_sta_sm(sm);
802}
803
804
805static void wpa_request_new_ptk(struct wpa_state_machine *sm)
806{
Hai Shalomfdcde762020-04-02 11:19:20 -0700807 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700808 return;
809
Hai Shalomfdcde762020-04-02 11:19:20 -0700810 if (!sm->use_ext_key_id && sm->wpa_auth->conf.wpa_deny_ptk0_rekey) {
811 wpa_printf(MSG_INFO,
812 "WPA: PTK0 rekey not allowed, disconnect " MACSTR,
813 MAC2STR(sm->addr));
Hai Shalome21d4e82020-04-29 16:34:06 -0700814 sm->Disconnect = true;
Hai Shalomfdcde762020-04-02 11:19:20 -0700815 /* Try to encourage the STA to reconnect */
816 sm->disconnect_reason =
817 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA;
818 } else {
819 if (sm->use_ext_key_id)
820 sm->keyidx_active ^= 1; /* flip Key ID */
Hai Shalome21d4e82020-04-29 16:34:06 -0700821 sm->PTKRequest = true;
Hai Shalomfdcde762020-04-02 11:19:20 -0700822 sm->PTK_valid = 0;
823 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700824}
825
826
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800827static int wpa_replay_counter_valid(struct wpa_key_replay_counter *ctr,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700828 const u8 *replay_counter)
829{
830 int i;
831 for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800832 if (!ctr[i].valid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700833 break;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800834 if (os_memcmp(replay_counter, ctr[i].counter,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700835 WPA_REPLAY_COUNTER_LEN) == 0)
836 return 1;
837 }
838 return 0;
839}
840
841
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800842static void wpa_replay_counter_mark_invalid(struct wpa_key_replay_counter *ctr,
843 const u8 *replay_counter)
844{
845 int i;
846 for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) {
847 if (ctr[i].valid &&
Hai Shalomfdcde762020-04-02 11:19:20 -0700848 (!replay_counter ||
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800849 os_memcmp(replay_counter, ctr[i].counter,
850 WPA_REPLAY_COUNTER_LEN) == 0))
Hai Shalome21d4e82020-04-29 16:34:06 -0700851 ctr[i].valid = false;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800852 }
853}
854
855
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800856#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700857static int ft_check_msg_2_of_4(struct wpa_authenticator *wpa_auth,
858 struct wpa_state_machine *sm,
859 struct wpa_eapol_ie_parse *kde)
860{
861 struct wpa_ie_data ie;
862 struct rsn_mdie *mdie;
863
864 if (wpa_parse_wpa_ie_rsn(kde->rsn_ie, kde->rsn_ie_len, &ie) < 0 ||
Hai Shalomfdcde762020-04-02 11:19:20 -0700865 ie.num_pmkid != 1 || !ie.pmkid) {
866 wpa_printf(MSG_DEBUG,
867 "FT: No PMKR1Name in FT 4-way handshake message 2/4");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700868 return -1;
869 }
870
871 os_memcpy(sm->sup_pmk_r1_name, ie.pmkid, PMKID_LEN);
872 wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from Supplicant",
873 sm->sup_pmk_r1_name, PMKID_LEN);
874
875 if (!kde->mdie || !kde->ftie) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700876 wpa_printf(MSG_DEBUG,
877 "FT: No %s in FT 4-way handshake message 2/4",
878 kde->mdie ? "FTIE" : "MDIE");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700879 return -1;
880 }
881
882 mdie = (struct rsn_mdie *) (kde->mdie + 2);
883 if (kde->mdie[1] < sizeof(struct rsn_mdie) ||
884 os_memcmp(wpa_auth->conf.mobility_domain, mdie->mobility_domain,
885 MOBILITY_DOMAIN_ID_LEN) != 0) {
886 wpa_printf(MSG_DEBUG, "FT: MDIE mismatch");
887 return -1;
888 }
889
890 if (sm->assoc_resp_ftie &&
891 (kde->ftie[1] != sm->assoc_resp_ftie[1] ||
892 os_memcmp(kde->ftie, sm->assoc_resp_ftie,
893 2 + sm->assoc_resp_ftie[1]) != 0)) {
894 wpa_printf(MSG_DEBUG, "FT: FTIE mismatch");
895 wpa_hexdump(MSG_DEBUG, "FT: FTIE in EAPOL-Key msg 2/4",
896 kde->ftie, kde->ftie_len);
897 wpa_hexdump(MSG_DEBUG, "FT: FTIE in (Re)AssocResp",
898 sm->assoc_resp_ftie, 2 + sm->assoc_resp_ftie[1]);
899 return -1;
900 }
901
902 return 0;
903}
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800904#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700905
906
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800907static int wpa_receive_error_report(struct wpa_authenticator *wpa_auth,
908 struct wpa_state_machine *sm, int group)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800909{
910 /* Supplicant reported a Michael MIC error */
911 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -0700912 "received EAPOL-Key Error Request (STA detected Michael MIC failure (group=%d))",
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800913 group);
914
915 if (group && wpa_auth->conf.wpa_group != 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 group cipher is not TKIP");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800918 } else if (!group && sm->pairwise != WPA_CIPHER_TKIP) {
919 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -0700920 "ignore Michael MIC failure report since pairwise cipher is not TKIP");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800921 } else {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800922 if (wpa_auth_mic_failure_report(wpa_auth, sm->addr) > 0)
923 return 1; /* STA entry was removed */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800924 sm->dot11RSNAStatsTKIPRemoteMICFailures++;
925 wpa_auth->dot11RSNAStatsTKIPRemoteMICFailures++;
926 }
927
928 /*
929 * Error report is not a request for a new key handshake, but since
930 * Authenticator may do it, let's change the keys now anyway.
931 */
932 wpa_request_new_ptk(sm);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800933 return 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800934}
935
936
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800937static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data,
938 size_t data_len)
939{
940 struct wpa_ptk PTK;
941 int ok = 0;
942 const u8 *pmk = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700943 size_t pmk_len;
Hai Shalom021b0b52019-04-10 11:17:58 -0700944 int vlan_id = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800945
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800946 os_memset(&PTK, 0, sizeof(PTK));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800947 for (;;) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700948 if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
949 !wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800950 pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr,
Hai Shalom021b0b52019-04-10 11:17:58 -0700951 sm->p2p_dev_addr, pmk, &pmk_len,
952 &vlan_id);
Hai Shalomfdcde762020-04-02 11:19:20 -0700953 if (!pmk)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800954 break;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700955#ifdef CONFIG_IEEE80211R_AP
956 if (wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) {
957 os_memcpy(sm->xxkey, pmk, pmk_len);
958 sm->xxkey_len = pmk_len;
959 }
960#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800961 } else {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800962 pmk = sm->PMK;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800963 pmk_len = sm->pmk_len;
964 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800965
Hai Shalomfdcde762020-04-02 11:19:20 -0700966 if (wpa_derive_ptk(sm, sm->alt_SNonce, pmk, pmk_len, &PTK, 0) <
967 0)
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800968 break;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800969
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700970 if (wpa_verify_key_mic(sm->wpa_key_mgmt, pmk_len, &PTK,
971 data, data_len) == 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -0700972 if (sm->PMK != pmk) {
973 os_memcpy(sm->PMK, pmk, pmk_len);
974 sm->pmk_len = pmk_len;
975 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800976 ok = 1;
977 break;
978 }
979
Roshan Pius3a1667e2018-07-03 15:17:14 -0700980 if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
981 wpa_key_mgmt_sae(sm->wpa_key_mgmt))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800982 break;
983 }
984
985 if (!ok) {
986 wpa_printf(MSG_DEBUG,
987 "WPA: Earlier SNonce did not result in matching MIC");
988 return -1;
989 }
990
991 wpa_printf(MSG_DEBUG,
992 "WPA: Earlier SNonce resulted in matching MIC");
993 sm->alt_snonce_valid = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -0700994
995 if (vlan_id && wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
996 wpa_auth_update_vlan(sm->wpa_auth, sm->addr, vlan_id) < 0)
997 return -1;
998
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800999 os_memcpy(sm->SNonce, sm->alt_SNonce, WPA_NONCE_LEN);
1000 os_memcpy(&sm->PTK, &PTK, sizeof(PTK));
Hai Shalom81f62d82019-07-22 12:10:00 -07001001 forced_memzero(&PTK, sizeof(PTK));
Hai Shalome21d4e82020-04-29 16:34:06 -07001002 sm->PTK_valid = true;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001003
1004 return 0;
1005}
1006
1007
Hai Shaloma20dcd72022-02-04 13:43:00 -08001008static bool wpa_auth_gtk_rekey_in_process(struct wpa_authenticator *wpa_auth)
1009{
1010 struct wpa_group *group;
1011
1012 for (group = wpa_auth->group; group; group = group->next) {
1013 if (group->GKeyDoneStations)
1014 return true;
1015 }
1016 return false;
1017}
1018
1019
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001020void wpa_receive(struct wpa_authenticator *wpa_auth,
1021 struct wpa_state_machine *sm,
1022 u8 *data, size_t data_len)
1023{
1024 struct ieee802_1x_hdr *hdr;
1025 struct wpa_eapol_key *key;
1026 u16 key_info, key_data_length;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001027 enum { PAIRWISE_2, PAIRWISE_4, GROUP_2, REQUEST } msg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001028 char *msgtxt;
1029 struct wpa_eapol_ie_parse kde;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001030 const u8 *key_data;
1031 size_t keyhdrlen, mic_len;
1032 u8 *mic;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001033
Hai Shalomfdcde762020-04-02 11:19:20 -07001034 if (!wpa_auth || !wpa_auth->conf.wpa || !sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001035 return;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001036 wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL data", data, data_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001037
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001038 mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001039 keyhdrlen = sizeof(*key) + mic_len + 2;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001040
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001041 if (data_len < sizeof(*hdr) + keyhdrlen) {
1042 wpa_printf(MSG_DEBUG, "WPA: Ignore too short EAPOL-Key frame");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001043 return;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001044 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001045
1046 hdr = (struct ieee802_1x_hdr *) data;
1047 key = (struct wpa_eapol_key *) (hdr + 1);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001048 mic = (u8 *) (key + 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001049 key_info = WPA_GET_BE16(key->key_info);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001050 key_data = mic + mic_len + 2;
1051 key_data_length = WPA_GET_BE16(mic + mic_len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001052 wpa_printf(MSG_DEBUG, "WPA: Received EAPOL-Key from " MACSTR
Hai Shalomfdcde762020-04-02 11:19:20 -07001053 " key_info=0x%x type=%u mic_len=%zu key_data_length=%u",
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001054 MAC2STR(sm->addr), key_info, key->type,
Hai Shalomfdcde762020-04-02 11:19:20 -07001055 mic_len, key_data_length);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001056 wpa_hexdump(MSG_MSGDUMP,
1057 "WPA: EAPOL-Key header (ending before Key MIC)",
1058 key, sizeof(*key));
1059 wpa_hexdump(MSG_MSGDUMP, "WPA: EAPOL-Key Key MIC",
1060 mic, mic_len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001061 if (key_data_length > data_len - sizeof(*hdr) - keyhdrlen) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001062 wpa_printf(MSG_INFO,
1063 "WPA: Invalid EAPOL-Key frame - key_data overflow (%d > %zu)",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001064 key_data_length,
Hai Shalomfdcde762020-04-02 11:19:20 -07001065 data_len - sizeof(*hdr) - keyhdrlen);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001066 return;
1067 }
1068
1069 if (sm->wpa == WPA_VERSION_WPA2) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001070 if (key->type == EAPOL_KEY_TYPE_WPA) {
1071 /*
1072 * Some deployed station implementations seem to send
1073 * msg 4/4 with incorrect type value in WPA2 mode.
1074 */
Hai Shalomfdcde762020-04-02 11:19:20 -07001075 wpa_printf(MSG_DEBUG,
1076 "Workaround: Allow EAPOL-Key with unexpected WPA type in RSN mode");
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001077 } else if (key->type != EAPOL_KEY_TYPE_RSN) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001078 wpa_printf(MSG_DEBUG,
1079 "Ignore EAPOL-Key with unexpected type %d in RSN mode",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001080 key->type);
1081 return;
1082 }
1083 } else {
1084 if (key->type != EAPOL_KEY_TYPE_WPA) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001085 wpa_printf(MSG_DEBUG,
1086 "Ignore EAPOL-Key with unexpected type %d in WPA mode",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001087 key->type);
1088 return;
1089 }
1090 }
1091
1092 wpa_hexdump(MSG_DEBUG, "WPA: Received Key Nonce", key->key_nonce,
1093 WPA_NONCE_LEN);
1094 wpa_hexdump(MSG_DEBUG, "WPA: Received Replay Counter",
1095 key->replay_counter, WPA_REPLAY_COUNTER_LEN);
1096
1097 /* FIX: verify that the EAPOL-Key frame was encrypted if pairwise keys
1098 * are set */
1099
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001100 if (key_info & WPA_KEY_INFO_SMK_MESSAGE) {
1101 wpa_printf(MSG_DEBUG, "WPA: Ignore SMK message");
1102 return;
1103 }
1104
1105 if (key_info & WPA_KEY_INFO_REQUEST) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001106 msg = REQUEST;
1107 msgtxt = "Request";
1108 } else if (!(key_info & WPA_KEY_INFO_KEY_TYPE)) {
1109 msg = GROUP_2;
1110 msgtxt = "2/2 Group";
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001111 } else if (key_data_length == 0 ||
1112 (mic_len == 0 && (key_info & WPA_KEY_INFO_ENCR_KEY_DATA) &&
1113 key_data_length == AES_BLOCK_SIZE)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001114 msg = PAIRWISE_4;
1115 msgtxt = "4/4 Pairwise";
1116 } else {
1117 msg = PAIRWISE_2;
1118 msgtxt = "2/4 Pairwise";
1119 }
1120
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001121 if (msg == REQUEST || msg == PAIRWISE_2 || msg == PAIRWISE_4 ||
1122 msg == GROUP_2) {
1123 u16 ver = key_info & WPA_KEY_INFO_TYPE_MASK;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001124 if (sm->pairwise == WPA_CIPHER_CCMP ||
1125 sm->pairwise == WPA_CIPHER_GCMP) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001126 if (wpa_use_cmac(sm->wpa_key_mgmt) &&
1127 !wpa_use_akm_defined(sm->wpa_key_mgmt) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001128 ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) {
1129 wpa_auth_logger(wpa_auth, sm->addr,
1130 LOGGER_WARNING,
Hai Shalomfdcde762020-04-02 11:19:20 -07001131 "advertised support for AES-128-CMAC, but did not use it");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001132 return;
1133 }
1134
Roshan Pius3a1667e2018-07-03 15:17:14 -07001135 if (!wpa_use_cmac(sm->wpa_key_mgmt) &&
1136 !wpa_use_akm_defined(sm->wpa_key_mgmt) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001137 ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
1138 wpa_auth_logger(wpa_auth, sm->addr,
1139 LOGGER_WARNING,
Hai Shalomfdcde762020-04-02 11:19:20 -07001140 "did not use HMAC-SHA1-AES with CCMP/GCMP");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001141 return;
1142 }
1143 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001144
Roshan Pius3a1667e2018-07-03 15:17:14 -07001145 if (wpa_use_akm_defined(sm->wpa_key_mgmt) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001146 ver != WPA_KEY_INFO_TYPE_AKM_DEFINED) {
1147 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING,
1148 "did not use EAPOL-Key descriptor version 0 as required for AKM-defined cases");
1149 return;
1150 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001151 }
1152
1153 if (key_info & WPA_KEY_INFO_REQUEST) {
1154 if (sm->req_replay_counter_used &&
1155 os_memcmp(key->replay_counter, sm->req_replay_counter,
1156 WPA_REPLAY_COUNTER_LEN) <= 0) {
1157 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING,
Hai Shalomfdcde762020-04-02 11:19:20 -07001158 "received EAPOL-Key request with replayed counter");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001159 return;
1160 }
1161 }
1162
1163 if (!(key_info & WPA_KEY_INFO_REQUEST) &&
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001164 !wpa_replay_counter_valid(sm->key_replay, key->replay_counter)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001165 int i;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001166
1167 if (msg == PAIRWISE_2 &&
1168 wpa_replay_counter_valid(sm->prev_key_replay,
1169 key->replay_counter) &&
1170 sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING &&
1171 os_memcmp(sm->SNonce, key->key_nonce, WPA_NONCE_LEN) != 0)
1172 {
1173 /*
1174 * Some supplicant implementations (e.g., Windows XP
1175 * WZC) update SNonce for each EAPOL-Key 2/4. This
1176 * breaks the workaround on accepting any of the
1177 * pending requests, so allow the SNonce to be updated
1178 * even if we have already sent out EAPOL-Key 3/4.
1179 */
1180 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07001181 "Process SNonce update from STA based on retransmitted EAPOL-Key 1/4");
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001182 sm->update_snonce = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001183 os_memcpy(sm->alt_SNonce, sm->SNonce, WPA_NONCE_LEN);
Hai Shalome21d4e82020-04-29 16:34:06 -07001184 sm->alt_snonce_valid = true;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001185 os_memcpy(sm->alt_replay_counter,
1186 sm->key_replay[0].counter,
1187 WPA_REPLAY_COUNTER_LEN);
1188 goto continue_processing;
1189 }
1190
1191 if (msg == PAIRWISE_4 && sm->alt_snonce_valid &&
1192 sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING &&
1193 os_memcmp(key->replay_counter, sm->alt_replay_counter,
1194 WPA_REPLAY_COUNTER_LEN) == 0) {
1195 /*
1196 * Supplicant may still be using the old SNonce since
1197 * there was two EAPOL-Key 2/4 messages and they had
1198 * different SNonce values.
1199 */
1200 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
1201 "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 -08001202 goto continue_processing;
1203 }
1204
1205 if (msg == PAIRWISE_2 &&
1206 wpa_replay_counter_valid(sm->prev_key_replay,
1207 key->replay_counter) &&
1208 sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING) {
1209 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07001210 "ignore retransmitted EAPOL-Key %s - SNonce did not change",
1211 msgtxt);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001212 } else {
1213 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07001214 "received EAPOL-Key %s with unexpected replay counter",
1215 msgtxt);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001216 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001217 for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) {
1218 if (!sm->key_replay[i].valid)
1219 break;
1220 wpa_hexdump(MSG_DEBUG, "pending replay counter",
1221 sm->key_replay[i].counter,
1222 WPA_REPLAY_COUNTER_LEN);
1223 }
1224 wpa_hexdump(MSG_DEBUG, "received replay counter",
1225 key->replay_counter, WPA_REPLAY_COUNTER_LEN);
1226 return;
1227 }
1228
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001229continue_processing:
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001230#ifdef CONFIG_FILS
1231 if (sm->wpa == WPA_VERSION_WPA2 && mic_len == 0 &&
1232 !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
1233 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
1234 "WPA: Encr Key Data bit not set even though AEAD cipher is supposed to be used - drop frame");
1235 return;
1236 }
1237#endif /* CONFIG_FILS */
1238
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001239 switch (msg) {
1240 case PAIRWISE_2:
1241 if (sm->wpa_ptk_state != WPA_PTK_PTKSTART &&
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001242 sm->wpa_ptk_state != WPA_PTK_PTKCALCNEGOTIATING &&
1243 (!sm->update_snonce ||
1244 sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001245 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001246 "received EAPOL-Key msg 2/4 in invalid state (%d) - dropped",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001247 sm->wpa_ptk_state);
1248 return;
1249 }
1250 random_add_randomness(key->key_nonce, WPA_NONCE_LEN);
1251 if (sm->group->reject_4way_hs_for_entropy) {
1252 /*
1253 * The system did not have enough entropy to generate
1254 * strong random numbers. Reject the first 4-way
1255 * handshake(s) and collect some entropy based on the
1256 * information from it. Once enough entropy is
1257 * available, the next atempt will trigger GMK/Key
1258 * Counter update and the station will be allowed to
1259 * continue.
1260 */
Hai Shalomfdcde762020-04-02 11:19:20 -07001261 wpa_printf(MSG_DEBUG,
1262 "WPA: Reject 4-way handshake to collect more entropy for random number generation");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001263 random_mark_pool_ready();
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001264 wpa_sta_disconnect(wpa_auth, sm->addr,
1265 WLAN_REASON_PREV_AUTH_NOT_VALID);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001266 return;
1267 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001268 break;
1269 case PAIRWISE_4:
1270 if (sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING ||
1271 !sm->PTK_valid) {
1272 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001273 "received EAPOL-Key msg 4/4 in invalid state (%d) - dropped",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001274 sm->wpa_ptk_state);
1275 return;
1276 }
1277 break;
1278 case GROUP_2:
1279 if (sm->wpa_ptk_group_state != WPA_PTK_GROUP_REKEYNEGOTIATING
1280 || !sm->PTK_valid) {
1281 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001282 "received EAPOL-Key msg 2/2 in invalid state (%d) - dropped",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001283 sm->wpa_ptk_group_state);
1284 return;
1285 }
1286 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001287 case REQUEST:
1288 break;
1289 }
1290
1291 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
1292 "received EAPOL-Key frame (%s)", msgtxt);
1293
1294 if (key_info & WPA_KEY_INFO_ACK) {
1295 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
1296 "received invalid EAPOL-Key: Key Ack set");
1297 return;
1298 }
1299
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001300 if (!wpa_key_mgmt_fils(sm->wpa_key_mgmt) &&
1301 !(key_info & WPA_KEY_INFO_MIC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001302 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
1303 "received invalid EAPOL-Key: Key MIC not set");
1304 return;
1305 }
1306
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001307#ifdef CONFIG_FILS
1308 if (wpa_key_mgmt_fils(sm->wpa_key_mgmt) &&
1309 (key_info & WPA_KEY_INFO_MIC)) {
1310 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
1311 "received invalid EAPOL-Key: Key MIC set");
1312 return;
1313 }
1314#endif /* CONFIG_FILS */
1315
Hai Shalome21d4e82020-04-29 16:34:06 -07001316 sm->MICVerified = false;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001317 if (sm->PTK_valid && !sm->update_snonce) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001318 if (mic_len &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001319 wpa_verify_key_mic(sm->wpa_key_mgmt, sm->pmk_len, &sm->PTK,
1320 data, data_len) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001321 (msg != PAIRWISE_4 || !sm->alt_snonce_valid ||
1322 wpa_try_alt_snonce(sm, data, data_len))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001323 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
1324 "received EAPOL-Key with invalid MIC");
Hai Shalom74f70d42019-02-11 14:42:39 -08001325#ifdef TEST_FUZZ
1326 wpa_printf(MSG_INFO,
1327 "TEST: Ignore Key MIC failure for fuzz testing");
1328 goto continue_fuzz;
1329#endif /* TEST_FUZZ */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001330 return;
1331 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001332#ifdef CONFIG_FILS
1333 if (!mic_len &&
1334 wpa_aead_decrypt(sm, &sm->PTK, data, data_len,
1335 &key_data_length) < 0) {
1336 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
1337 "received EAPOL-Key with invalid MIC");
Hai Shalom74f70d42019-02-11 14:42:39 -08001338#ifdef TEST_FUZZ
1339 wpa_printf(MSG_INFO,
1340 "TEST: Ignore Key MIC failure for fuzz testing");
1341 goto continue_fuzz;
1342#endif /* TEST_FUZZ */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001343 return;
1344 }
1345#endif /* CONFIG_FILS */
Hai Shalom74f70d42019-02-11 14:42:39 -08001346#ifdef TEST_FUZZ
1347 continue_fuzz:
1348#endif /* TEST_FUZZ */
Hai Shalome21d4e82020-04-29 16:34:06 -07001349 sm->MICVerified = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001350 eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm);
1351 sm->pending_1_of_4_timeout = 0;
1352 }
1353
1354 if (key_info & WPA_KEY_INFO_REQUEST) {
1355 if (sm->MICVerified) {
1356 sm->req_replay_counter_used = 1;
1357 os_memcpy(sm->req_replay_counter, key->replay_counter,
1358 WPA_REPLAY_COUNTER_LEN);
1359 } else {
1360 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001361 "received EAPOL-Key request with invalid MIC");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001362 return;
1363 }
1364
1365 /*
1366 * TODO: should decrypt key data field if encryption was used;
1367 * even though MAC address KDE is not normally encrypted,
1368 * supplicant is allowed to encrypt it.
1369 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001370 if (key_info & WPA_KEY_INFO_ERROR) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001371 if (wpa_receive_error_report(
1372 wpa_auth, sm,
1373 !(key_info & WPA_KEY_INFO_KEY_TYPE)) > 0)
1374 return; /* STA entry was removed */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001375 } else if (key_info & WPA_KEY_INFO_KEY_TYPE) {
1376 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001377 "received EAPOL-Key Request for new 4-Way Handshake");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001378 wpa_request_new_ptk(sm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001379 } else if (key_data_length > 0 &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001380 wpa_parse_kde_ies(key_data, key_data_length,
1381 &kde) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001382 kde.mac_addr) {
1383 } else {
1384 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001385 "received EAPOL-Key Request for GTK rekeying");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001386 eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL);
Hai Shaloma20dcd72022-02-04 13:43:00 -08001387 if (wpa_auth_gtk_rekey_in_process(wpa_auth))
1388 wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG,
1389 "skip new GTK rekey - already in process");
1390 else
1391 wpa_rekey_gtk(wpa_auth, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001392 }
1393 } else {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001394 /* Do not allow the same key replay counter to be reused. */
1395 wpa_replay_counter_mark_invalid(sm->key_replay,
1396 key->replay_counter);
1397
1398 if (msg == PAIRWISE_2) {
1399 /*
1400 * Maintain a copy of the pending EAPOL-Key frames in
1401 * case the EAPOL-Key frame was retransmitted. This is
1402 * needed to allow EAPOL-Key msg 2/4 reply to another
1403 * pending msg 1/4 to update the SNonce to work around
1404 * unexpected supplicant behavior.
1405 */
1406 os_memcpy(sm->prev_key_replay, sm->key_replay,
1407 sizeof(sm->key_replay));
1408 } else {
1409 os_memset(sm->prev_key_replay, 0,
1410 sizeof(sm->prev_key_replay));
1411 }
1412
1413 /*
1414 * Make sure old valid counters are not accepted anymore and
1415 * do not get copied again.
1416 */
1417 wpa_replay_counter_mark_invalid(sm->key_replay, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001418 }
1419
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001420 os_free(sm->last_rx_eapol_key);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001421 sm->last_rx_eapol_key = os_memdup(data, data_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07001422 if (!sm->last_rx_eapol_key)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001423 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001424 sm->last_rx_eapol_key_len = data_len;
1425
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001426 sm->rx_eapol_key_secure = !!(key_info & WPA_KEY_INFO_SECURE);
Hai Shalome21d4e82020-04-29 16:34:06 -07001427 sm->EAPOLKeyReceived = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001428 sm->EAPOLKeyPairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE);
1429 sm->EAPOLKeyRequest = !!(key_info & WPA_KEY_INFO_REQUEST);
1430 os_memcpy(sm->SNonce, key->key_nonce, WPA_NONCE_LEN);
1431 wpa_sm_step(sm);
1432}
1433
1434
1435static int wpa_gmk_to_gtk(const u8 *gmk, const char *label, const u8 *addr,
1436 const u8 *gnonce, u8 *gtk, size_t gtk_len)
1437{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001438 u8 data[ETH_ALEN + WPA_NONCE_LEN + 8 + WPA_GTK_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001439 u8 *pos;
1440 int ret = 0;
1441
1442 /* GTK = PRF-X(GMK, "Group key expansion",
1443 * AA || GNonce || Time || random data)
1444 * The example described in the IEEE 802.11 standard uses only AA and
1445 * GNonce as inputs here. Add some more entropy since this derivation
1446 * is done only at the Authenticator and as such, does not need to be
1447 * exactly same.
1448 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001449 os_memset(data, 0, sizeof(data));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001450 os_memcpy(data, addr, ETH_ALEN);
1451 os_memcpy(data + ETH_ALEN, gnonce, WPA_NONCE_LEN);
1452 pos = data + ETH_ALEN + WPA_NONCE_LEN;
1453 wpa_get_ntp_timestamp(pos);
Hai Shalom74f70d42019-02-11 14:42:39 -08001454#ifdef TEST_FUZZ
1455 os_memset(pos, 0xef, 8);
1456#endif /* TEST_FUZZ */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001457 pos += 8;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001458 if (random_get_bytes(pos, gtk_len) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001459 ret = -1;
1460
Roshan Pius3a1667e2018-07-03 15:17:14 -07001461#ifdef CONFIG_SHA384
1462 if (sha384_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data),
1463 gtk, gtk_len) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001464 ret = -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001465#else /* CONFIG_SHA384 */
1466#ifdef CONFIG_SHA256
1467 if (sha256_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data),
1468 gtk, gtk_len) < 0)
1469 ret = -1;
1470#else /* CONFIG_SHA256 */
1471 if (sha1_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data),
1472 gtk, gtk_len) < 0)
1473 ret = -1;
1474#endif /* CONFIG_SHA256 */
1475#endif /* CONFIG_SHA384 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001476
Hai Shalom81f62d82019-07-22 12:10:00 -07001477 forced_memzero(data, sizeof(data));
1478
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001479 return ret;
1480}
1481
1482
1483static void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx)
1484{
1485 struct wpa_authenticator *wpa_auth = eloop_ctx;
1486 struct wpa_state_machine *sm = timeout_ctx;
1487
Sunil Ravia04bd252022-05-02 22:54:18 -07001488 if (sm->waiting_radius_psk) {
1489 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
1490 "Ignore EAPOL-Key timeout while waiting for RADIUS PSK");
1491 return;
1492 }
1493
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001494 sm->pending_1_of_4_timeout = 0;
1495 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "EAPOL-Key timeout");
Hai Shalome21d4e82020-04-29 16:34:06 -07001496 sm->TimeoutEvt = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001497 wpa_sm_step(sm);
1498}
1499
1500
1501void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
1502 struct wpa_state_machine *sm, int key_info,
1503 const u8 *key_rsc, const u8 *nonce,
1504 const u8 *kde, size_t kde_len,
1505 int keyidx, int encr, int force_version)
1506{
Hai Shalomfdcde762020-04-02 11:19:20 -07001507 struct wpa_auth_config *conf = &wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001508 struct ieee802_1x_hdr *hdr;
1509 struct wpa_eapol_key *key;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001510 size_t len, mic_len, keyhdrlen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001511 int alg;
1512 int key_data_len, pad_len = 0;
1513 u8 *buf, *pos;
1514 int version, pairwise;
1515 int i;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001516 u8 *key_mic, *key_data;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001517
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001518 mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001519 keyhdrlen = sizeof(*key) + mic_len + 2;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001520
1521 len = sizeof(struct ieee802_1x_hdr) + keyhdrlen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001522
1523 if (force_version)
1524 version = force_version;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001525 else if (wpa_use_akm_defined(sm->wpa_key_mgmt))
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001526 version = WPA_KEY_INFO_TYPE_AKM_DEFINED;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001527 else if (wpa_use_cmac(sm->wpa_key_mgmt))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001528 version = WPA_KEY_INFO_TYPE_AES_128_CMAC;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001529 else if (sm->pairwise != WPA_CIPHER_TKIP)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001530 version = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;
1531 else
1532 version = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
1533
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001534 pairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001535
Hai Shalomfdcde762020-04-02 11:19:20 -07001536 wpa_printf(MSG_DEBUG,
1537 "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 -07001538 version,
1539 (key_info & WPA_KEY_INFO_SECURE) ? 1 : 0,
1540 (key_info & WPA_KEY_INFO_MIC) ? 1 : 0,
1541 (key_info & WPA_KEY_INFO_ACK) ? 1 : 0,
1542 (key_info & WPA_KEY_INFO_INSTALL) ? 1 : 0,
Hai Shalomfdcde762020-04-02 11:19:20 -07001543 pairwise, kde_len, keyidx, encr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001544
1545 key_data_len = kde_len;
1546
1547 if ((version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
Roshan Pius3a1667e2018-07-03 15:17:14 -07001548 wpa_use_aes_key_wrap(sm->wpa_key_mgmt) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001549 version == WPA_KEY_INFO_TYPE_AES_128_CMAC) && encr) {
1550 pad_len = key_data_len % 8;
1551 if (pad_len)
1552 pad_len = 8 - pad_len;
1553 key_data_len += pad_len + 8;
1554 }
1555
1556 len += key_data_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001557 if (!mic_len && encr)
1558 len += AES_BLOCK_SIZE;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001559
1560 hdr = os_zalloc(len);
Hai Shalomfdcde762020-04-02 11:19:20 -07001561 if (!hdr)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001562 return;
Hai Shalomfdcde762020-04-02 11:19:20 -07001563 hdr->version = conf->eapol_version;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001564 hdr->type = IEEE802_1X_TYPE_EAPOL_KEY;
1565 hdr->length = host_to_be16(len - sizeof(*hdr));
1566 key = (struct wpa_eapol_key *) (hdr + 1);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001567 key_mic = (u8 *) (key + 1);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001568 key_data = ((u8 *) (hdr + 1)) + keyhdrlen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001569
1570 key->type = sm->wpa == WPA_VERSION_WPA2 ?
1571 EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
1572 key_info |= version;
1573 if (encr && sm->wpa == WPA_VERSION_WPA2)
1574 key_info |= WPA_KEY_INFO_ENCR_KEY_DATA;
1575 if (sm->wpa != WPA_VERSION_WPA2)
1576 key_info |= keyidx << WPA_KEY_INFO_KEY_INDEX_SHIFT;
1577 WPA_PUT_BE16(key->key_info, key_info);
1578
Hai Shalomfdcde762020-04-02 11:19:20 -07001579 alg = pairwise ? sm->pairwise : conf->wpa_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001580 if (sm->wpa == WPA_VERSION_WPA2 && !pairwise)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001581 WPA_PUT_BE16(key->key_length, 0);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001582 else
1583 WPA_PUT_BE16(key->key_length, wpa_cipher_key_len(alg));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001584
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001585 for (i = RSNA_MAX_EAPOL_RETRIES - 1; i > 0; i--) {
1586 sm->key_replay[i].valid = sm->key_replay[i - 1].valid;
1587 os_memcpy(sm->key_replay[i].counter,
1588 sm->key_replay[i - 1].counter,
1589 WPA_REPLAY_COUNTER_LEN);
1590 }
1591 inc_byte_array(sm->key_replay[0].counter, WPA_REPLAY_COUNTER_LEN);
1592 os_memcpy(key->replay_counter, sm->key_replay[0].counter,
1593 WPA_REPLAY_COUNTER_LEN);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001594 wpa_hexdump(MSG_DEBUG, "WPA: Replay Counter",
1595 key->replay_counter, WPA_REPLAY_COUNTER_LEN);
Hai Shalome21d4e82020-04-29 16:34:06 -07001596 sm->key_replay[0].valid = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001597
1598 if (nonce)
1599 os_memcpy(key->key_nonce, nonce, WPA_NONCE_LEN);
1600
1601 if (key_rsc)
1602 os_memcpy(key->key_rsc, key_rsc, WPA_KEY_RSC_LEN);
1603
1604 if (kde && !encr) {
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001605 os_memcpy(key_data, kde, kde_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001606 WPA_PUT_BE16(key_mic + mic_len, kde_len);
1607#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07001608 } else if (!mic_len && kde) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001609 const u8 *aad[1];
1610 size_t aad_len[1];
1611
1612 WPA_PUT_BE16(key_mic, AES_BLOCK_SIZE + kde_len);
1613 wpa_hexdump_key(MSG_DEBUG, "Plaintext EAPOL-Key Key Data",
1614 kde, kde_len);
1615
1616 wpa_hexdump_key(MSG_DEBUG, "WPA: KEK",
1617 sm->PTK.kek, sm->PTK.kek_len);
1618 /* AES-SIV AAD from EAPOL protocol version field (inclusive) to
1619 * to Key Data (exclusive). */
1620 aad[0] = (u8 *) hdr;
1621 aad_len[0] = key_mic + 2 - (u8 *) hdr;
1622 if (aes_siv_encrypt(sm->PTK.kek, sm->PTK.kek_len, kde, kde_len,
1623 1, aad, aad_len, key_mic + 2) < 0) {
1624 wpa_printf(MSG_DEBUG, "WPA: AES-SIV encryption failed");
1625 return;
1626 }
1627
1628 wpa_hexdump(MSG_DEBUG, "WPA: Encrypted Key Data from SIV",
1629 key_mic + 2, AES_BLOCK_SIZE + kde_len);
1630#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001631 } else if (encr && kde) {
1632 buf = os_zalloc(key_data_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07001633 if (!buf) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001634 os_free(hdr);
1635 return;
1636 }
1637 pos = buf;
1638 os_memcpy(pos, kde, kde_len);
1639 pos += kde_len;
1640
1641 if (pad_len)
1642 *pos++ = 0xdd;
1643
1644 wpa_hexdump_key(MSG_DEBUG, "Plaintext EAPOL-Key Key Data",
1645 buf, key_data_len);
1646 if (version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
Roshan Pius3a1667e2018-07-03 15:17:14 -07001647 wpa_use_aes_key_wrap(sm->wpa_key_mgmt) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001648 version == WPA_KEY_INFO_TYPE_AES_128_CMAC) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001649 wpa_printf(MSG_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07001650 "WPA: Encrypt Key Data using AES-WRAP (KEK length %zu)",
1651 sm->PTK.kek_len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001652 if (aes_wrap(sm->PTK.kek, sm->PTK.kek_len,
1653 (key_data_len - 8) / 8, buf, key_data)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001654 os_free(hdr);
Sunil Ravia04bd252022-05-02 22:54:18 -07001655 bin_clear_free(buf, key_data_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001656 return;
1657 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001658 WPA_PUT_BE16(key_mic + mic_len, key_data_len);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001659#ifndef CONFIG_NO_RC4
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001660 } else if (sm->PTK.kek_len == 16) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001661 u8 ek[32];
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001662
1663 wpa_printf(MSG_DEBUG,
1664 "WPA: Encrypt Key Data using RC4");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001665 os_memcpy(key->key_iv,
1666 sm->group->Counter + WPA_NONCE_LEN - 16, 16);
1667 inc_byte_array(sm->group->Counter, WPA_NONCE_LEN);
1668 os_memcpy(ek, key->key_iv, 16);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001669 os_memcpy(ek + 16, sm->PTK.kek, sm->PTK.kek_len);
1670 os_memcpy(key_data, buf, key_data_len);
1671 rc4_skip(ek, 32, 256, key_data, key_data_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001672 WPA_PUT_BE16(key_mic + mic_len, key_data_len);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001673#endif /* CONFIG_NO_RC4 */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001674 } else {
1675 os_free(hdr);
Sunil Ravia04bd252022-05-02 22:54:18 -07001676 bin_clear_free(buf, key_data_len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001677 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001678 }
Sunil Ravia04bd252022-05-02 22:54:18 -07001679 bin_clear_free(buf, key_data_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001680 }
1681
1682 if (key_info & WPA_KEY_INFO_MIC) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001683 if (!sm->PTK_valid || !mic_len) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001684 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07001685 "PTK not valid when sending EAPOL-Key frame");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001686 os_free(hdr);
1687 return;
1688 }
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001689
Roshan Pius3a1667e2018-07-03 15:17:14 -07001690 if (wpa_eapol_key_mic(sm->PTK.kck, sm->PTK.kck_len,
1691 sm->wpa_key_mgmt, version,
1692 (u8 *) hdr, len, key_mic) < 0) {
1693 os_free(hdr);
1694 return;
1695 }
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001696#ifdef CONFIG_TESTING_OPTIONS
1697 if (!pairwise &&
Hai Shalomfdcde762020-04-02 11:19:20 -07001698 conf->corrupt_gtk_rekey_mic_probability > 0.0 &&
1699 drand48() < conf->corrupt_gtk_rekey_mic_probability) {
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001700 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
1701 "Corrupting group EAPOL-Key Key MIC");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001702 key_mic[0]++;
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001703 }
1704#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001705 }
1706
Hai Shalomfdcde762020-04-02 11:19:20 -07001707 wpa_auth_set_eapol(wpa_auth, sm->addr, WPA_EAPOL_inc_EapolFramesTx, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001708 wpa_auth_send_eapol(wpa_auth, sm->addr, (u8 *) hdr, len,
Kai Shie75b0652020-11-24 20:31:29 -08001709 sm->pairwise_set);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001710 os_free(hdr);
1711}
1712
1713
1714static void wpa_send_eapol(struct wpa_authenticator *wpa_auth,
1715 struct wpa_state_machine *sm, int key_info,
1716 const u8 *key_rsc, const u8 *nonce,
1717 const u8 *kde, size_t kde_len,
1718 int keyidx, int encr)
1719{
1720 int timeout_ms;
1721 int pairwise = key_info & WPA_KEY_INFO_KEY_TYPE;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001722 u32 ctr;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001723
Hai Shalomfdcde762020-04-02 11:19:20 -07001724 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001725 return;
1726
1727 __wpa_send_eapol(wpa_auth, sm, key_info, key_rsc, nonce, kde, kde_len,
1728 keyidx, encr, 0);
1729
1730 ctr = pairwise ? sm->TimeoutCtr : sm->GTimeoutCtr;
1731 if (ctr == 1 && wpa_auth->conf.tx_status)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001732 timeout_ms = pairwise ? eapol_key_timeout_first :
1733 eapol_key_timeout_first_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001734 else
1735 timeout_ms = eapol_key_timeout_subseq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001736 if (wpa_auth->conf.wpa_disable_eapol_key_retries &&
1737 (!pairwise || (key_info & WPA_KEY_INFO_MIC)))
1738 timeout_ms = eapol_key_timeout_no_retrans;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001739 if (pairwise && ctr == 1 && !(key_info & WPA_KEY_INFO_MIC))
1740 sm->pending_1_of_4_timeout = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08001741#ifdef TEST_FUZZ
1742 timeout_ms = 1;
1743#endif /* TEST_FUZZ */
Kai Shie75b0652020-11-24 20:31:29 -08001744#ifdef CONFIG_TESTING_OPTIONS
1745 if(wpa_auth->conf.enable_eapol_large_timeout) {
1746 timeout_ms = 50 * 1000;
1747 }
1748#endif
Hai Shalomfdcde762020-04-02 11:19:20 -07001749 wpa_printf(MSG_DEBUG,
1750 "WPA: Use EAPOL-Key timeout of %u ms (retry counter %u)",
1751 timeout_ms, ctr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001752 eloop_register_timeout(timeout_ms / 1000, (timeout_ms % 1000) * 1000,
1753 wpa_send_eapol_timeout, wpa_auth, sm);
1754}
1755
1756
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001757static int wpa_verify_key_mic(int akmp, size_t pmk_len, struct wpa_ptk *PTK,
1758 u8 *data, size_t data_len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001759{
1760 struct ieee802_1x_hdr *hdr;
1761 struct wpa_eapol_key *key;
1762 u16 key_info;
1763 int ret = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001764 u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN], *mic_pos;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001765 size_t mic_len = wpa_mic_len(akmp, pmk_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001766
1767 if (data_len < sizeof(*hdr) + sizeof(*key))
1768 return -1;
1769
1770 hdr = (struct ieee802_1x_hdr *) data;
1771 key = (struct wpa_eapol_key *) (hdr + 1);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001772 mic_pos = (u8 *) (key + 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001773 key_info = WPA_GET_BE16(key->key_info);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001774 os_memcpy(mic, mic_pos, mic_len);
1775 os_memset(mic_pos, 0, mic_len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001776 if (wpa_eapol_key_mic(PTK->kck, PTK->kck_len, akmp,
1777 key_info & WPA_KEY_INFO_TYPE_MASK,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001778 data, data_len, mic_pos) ||
1779 os_memcmp_const(mic, mic_pos, mic_len) != 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001780 ret = -1;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001781 os_memcpy(mic_pos, mic, mic_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001782 return ret;
1783}
1784
1785
1786void wpa_remove_ptk(struct wpa_state_machine *sm)
1787{
Hai Shalome21d4e82020-04-29 16:34:06 -07001788 sm->PTK_valid = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001789 os_memset(&sm->PTK, 0, sizeof(sm->PTK));
Hai Shalom60840252021-02-19 19:02:11 -08001790
1791 wpa_auth_remove_ptksa(sm->wpa_auth, sm->addr, sm->pairwise);
1792
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001793 if (wpa_auth_set_key(sm->wpa_auth, 0, WPA_ALG_NONE, sm->addr, 0, NULL,
Hai Shalomfdcde762020-04-02 11:19:20 -07001794 0, KEY_FLAG_PAIRWISE))
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001795 wpa_printf(MSG_DEBUG,
1796 "RSN: PTK removal from the driver failed");
Hai Shalomfdcde762020-04-02 11:19:20 -07001797 if (sm->use_ext_key_id &&
1798 wpa_auth_set_key(sm->wpa_auth, 0, WPA_ALG_NONE, sm->addr, 1, NULL,
1799 0, KEY_FLAG_PAIRWISE))
1800 wpa_printf(MSG_DEBUG,
1801 "RSN: PTK Key ID 1 removal from the driver failed");
Hai Shalome21d4e82020-04-29 16:34:06 -07001802 sm->pairwise_set = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001803 eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm);
1804}
1805
1806
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001807int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001808{
1809 int remove_ptk = 1;
1810
Hai Shalomfdcde762020-04-02 11:19:20 -07001811 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001812 return -1;
1813
1814 wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
1815 "event %d notification", event);
1816
1817 switch (event) {
1818 case WPA_AUTH:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001819#ifdef CONFIG_MESH
1820 /* PTKs are derived through AMPE */
1821 if (wpa_auth_start_ampe(sm->wpa_auth, sm->addr)) {
1822 /* not mesh */
1823 break;
1824 }
1825 return 0;
1826#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001827 case WPA_ASSOC:
1828 break;
1829 case WPA_DEAUTH:
1830 case WPA_DISASSOC:
Hai Shalome21d4e82020-04-29 16:34:06 -07001831 sm->DeauthenticationRequest = true;
Hai Shalom1dc4d202019-04-29 16:22:27 -07001832 os_memset(sm->PMK, 0, sizeof(sm->PMK));
1833 sm->pmk_len = 0;
Sunil Ravia04bd252022-05-02 22:54:18 -07001834#ifdef CONFIG_IEEE80211R_AP
Hai Shalom1dc4d202019-04-29 16:22:27 -07001835 os_memset(sm->xxkey, 0, sizeof(sm->xxkey));
1836 sm->xxkey_len = 0;
Hai Shalom81f62d82019-07-22 12:10:00 -07001837 os_memset(sm->pmk_r1, 0, sizeof(sm->pmk_r1));
1838 sm->pmk_r1_len = 0;
Hai Shalom1dc4d202019-04-29 16:22:27 -07001839#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001840 break;
1841 case WPA_REAUTH:
1842 case WPA_REAUTH_EAPOL:
1843 if (!sm->started) {
1844 /*
1845 * When using WPS, we may end up here if the STA
1846 * manages to re-associate without the previous STA
1847 * entry getting removed. Consequently, we need to make
1848 * sure that the WPA state machines gets initialized
1849 * properly at this point.
1850 */
Hai Shalomfdcde762020-04-02 11:19:20 -07001851 wpa_printf(MSG_DEBUG,
1852 "WPA state machine had not been started - initialize now");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001853 sm->started = 1;
Hai Shalome21d4e82020-04-29 16:34:06 -07001854 sm->Init = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001855 if (wpa_sm_step(sm) == 1)
1856 return 1; /* should not really happen */
Hai Shalome21d4e82020-04-29 16:34:06 -07001857 sm->Init = false;
1858 sm->AuthenticationRequest = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001859 break;
1860 }
Hai Shalomfdcde762020-04-02 11:19:20 -07001861
Sunil Ravia04bd252022-05-02 22:54:18 -07001862 if (sm->ptkstart_without_success > 3) {
1863 wpa_printf(MSG_INFO,
1864 "WPA: Multiple EAP reauth attempts without 4-way handshake completion, disconnect "
1865 MACSTR, MAC2STR(sm->addr));
1866 sm->Disconnect = true;
1867 break;
1868 }
1869
Hai Shalomfdcde762020-04-02 11:19:20 -07001870 if (!sm->use_ext_key_id &&
1871 sm->wpa_auth->conf.wpa_deny_ptk0_rekey) {
1872 wpa_printf(MSG_INFO,
1873 "WPA: PTK0 rekey not allowed, disconnect "
1874 MACSTR, MAC2STR(sm->addr));
Hai Shalome21d4e82020-04-29 16:34:06 -07001875 sm->Disconnect = true;
Hai Shalomfdcde762020-04-02 11:19:20 -07001876 /* Try to encourage the STA to reconnect */
1877 sm->disconnect_reason =
1878 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA;
1879 break;
1880 }
1881
1882 if (sm->use_ext_key_id)
1883 sm->keyidx_active ^= 1; /* flip Key ID */
1884
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001885 if (sm->GUpdateStationKeys) {
1886 /*
1887 * Reauthentication cancels the pending group key
1888 * update for this STA.
1889 */
1890 sm->group->GKeyDoneStations--;
Hai Shalome21d4e82020-04-29 16:34:06 -07001891 sm->GUpdateStationKeys = false;
1892 sm->PtkGroupInit = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001893 }
Hai Shalome21d4e82020-04-29 16:34:06 -07001894 sm->ReAuthenticationRequest = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001895 break;
1896 case WPA_ASSOC_FT:
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001897#ifdef CONFIG_IEEE80211R_AP
Hai Shalomfdcde762020-04-02 11:19:20 -07001898 wpa_printf(MSG_DEBUG,
1899 "FT: Retry PTK configuration after association");
Hai Shalomb755a2a2020-04-23 21:49:02 -07001900 wpa_ft_install_ptk(sm, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001901
1902 /* Using FT protocol, not WPA auth state machine */
1903 sm->ft_completed = 1;
Hai Shalom81f62d82019-07-22 12:10:00 -07001904 wpa_auth_set_ptk_rekey_timer(sm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001905 return 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001906#else /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001907 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001908#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001909 case WPA_ASSOC_FILS:
1910#ifdef CONFIG_FILS
1911 wpa_printf(MSG_DEBUG,
1912 "FILS: TK configuration after association");
1913 fils_set_tk(sm);
1914 sm->fils_completed = 1;
1915 return 0;
1916#else /* CONFIG_FILS */
1917 break;
1918#endif /* CONFIG_FILS */
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02001919 case WPA_DRV_STA_REMOVED:
Hai Shalome21d4e82020-04-29 16:34:06 -07001920 sm->tk_already_set = false;
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02001921 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001922 }
1923
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001924#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001925 sm->ft_completed = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001926#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001927
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001928 if (sm->mgmt_frame_prot && event == WPA_AUTH)
1929 remove_ptk = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001930#ifdef CONFIG_FILS
1931 if (wpa_key_mgmt_fils(sm->wpa_key_mgmt) &&
1932 (event == WPA_AUTH || event == WPA_ASSOC))
1933 remove_ptk = 0;
1934#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001935
1936 if (remove_ptk) {
Hai Shalome21d4e82020-04-29 16:34:06 -07001937 sm->PTK_valid = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001938 os_memset(&sm->PTK, 0, sizeof(sm->PTK));
1939
1940 if (event != WPA_REAUTH_EAPOL)
1941 wpa_remove_ptk(sm);
1942 }
1943
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001944 if (sm->in_step_loop) {
1945 /*
1946 * wpa_sm_step() is already running - avoid recursive call to
1947 * it by making the existing loop process the new update.
1948 */
Hai Shalome21d4e82020-04-29 16:34:06 -07001949 sm->changed = true;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001950 return 0;
1951 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001952 return wpa_sm_step(sm);
1953}
1954
1955
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001956SM_STATE(WPA_PTK, INITIALIZE)
1957{
1958 SM_ENTRY_MA(WPA_PTK, INITIALIZE, wpa_ptk);
1959 if (sm->Init) {
1960 /* Init flag is not cleared here, so avoid busy
1961 * loop by claiming nothing changed. */
Hai Shalome21d4e82020-04-29 16:34:06 -07001962 sm->changed = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001963 }
1964
1965 sm->keycount = 0;
1966 if (sm->GUpdateStationKeys)
1967 sm->group->GKeyDoneStations--;
Hai Shalome21d4e82020-04-29 16:34:06 -07001968 sm->GUpdateStationKeys = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001969 if (sm->wpa == WPA_VERSION_WPA)
Hai Shalome21d4e82020-04-29 16:34:06 -07001970 sm->PInitAKeys = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001971 if (1 /* Unicast cipher supported AND (ESS OR ((IBSS or WDS) and
1972 * Local AA > Remote AA)) */) {
Hai Shalome21d4e82020-04-29 16:34:06 -07001973 sm->Pair = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001974 }
1975 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 0);
1976 wpa_remove_ptk(sm);
1977 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid, 0);
1978 sm->TimeoutCtr = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001979 if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
1980 sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP ||
1981 sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001982 wpa_auth_set_eapol(sm->wpa_auth, sm->addr,
1983 WPA_EAPOL_authorized, 0);
1984 }
1985}
1986
1987
1988SM_STATE(WPA_PTK, DISCONNECT)
1989{
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001990 u16 reason = sm->disconnect_reason;
1991
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001992 SM_ENTRY_MA(WPA_PTK, DISCONNECT, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07001993 sm->Disconnect = false;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001994 sm->disconnect_reason = 0;
1995 if (!reason)
1996 reason = WLAN_REASON_PREV_AUTH_NOT_VALID;
1997 wpa_sta_disconnect(sm->wpa_auth, sm->addr, reason);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001998}
1999
2000
2001SM_STATE(WPA_PTK, DISCONNECTED)
2002{
2003 SM_ENTRY_MA(WPA_PTK, DISCONNECTED, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07002004 sm->DeauthenticationRequest = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002005}
2006
2007
2008SM_STATE(WPA_PTK, AUTHENTICATION)
2009{
2010 SM_ENTRY_MA(WPA_PTK, AUTHENTICATION, wpa_ptk);
2011 os_memset(&sm->PTK, 0, sizeof(sm->PTK));
Hai Shalome21d4e82020-04-29 16:34:06 -07002012 sm->PTK_valid = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002013 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portControl_Auto,
2014 1);
2015 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 1);
Hai Shalome21d4e82020-04-29 16:34:06 -07002016 sm->AuthenticationRequest = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002017}
2018
2019
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002020static void wpa_group_ensure_init(struct wpa_authenticator *wpa_auth,
2021 struct wpa_group *group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002022{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002023 if (group->first_sta_seen)
2024 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002025 /*
2026 * System has run bit further than at the time hostapd was started
2027 * potentially very early during boot up. This provides better chances
2028 * of collecting more randomness on embedded systems. Re-initialize the
2029 * GMK and Counter here to improve their strength if there was not
2030 * enough entropy available immediately after system startup.
2031 */
Hai Shalomfdcde762020-04-02 11:19:20 -07002032 wpa_printf(MSG_DEBUG,
2033 "WPA: Re-initialize GMK/Counter on first station");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002034 if (random_pool_ready() != 1) {
Hai Shalomfdcde762020-04-02 11:19:20 -07002035 wpa_printf(MSG_INFO,
2036 "WPA: Not enough entropy in random pool to proceed - reject first 4-way handshake");
Hai Shalome21d4e82020-04-29 16:34:06 -07002037 group->reject_4way_hs_for_entropy = true;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002038 } else {
Hai Shalome21d4e82020-04-29 16:34:06 -07002039 group->first_sta_seen = true;
2040 group->reject_4way_hs_for_entropy = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002041 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002042
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002043 if (wpa_group_init_gmk_and_counter(wpa_auth, group) < 0 ||
2044 wpa_gtk_update(wpa_auth, group) < 0 ||
2045 wpa_group_config_group_keys(wpa_auth, group) < 0) {
2046 wpa_printf(MSG_INFO, "WPA: GMK/GTK setup failed");
Hai Shalome21d4e82020-04-29 16:34:06 -07002047 group->first_sta_seen = false;
2048 group->reject_4way_hs_for_entropy = true;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002049 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002050}
2051
2052
2053SM_STATE(WPA_PTK, AUTHENTICATION2)
2054{
2055 SM_ENTRY_MA(WPA_PTK, AUTHENTICATION2, wpa_ptk);
2056
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002057 wpa_group_ensure_init(sm->wpa_auth, sm->group);
Hai Shalome21d4e82020-04-29 16:34:06 -07002058 sm->ReAuthenticationRequest = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002059
Dmitry Shmidt04949592012-07-19 12:16:46 -07002060 /*
2061 * Definition of ANonce selection in IEEE Std 802.11i-2004 is somewhat
2062 * ambiguous. The Authenticator state machine uses a counter that is
2063 * incremented by one for each 4-way handshake. However, the security
2064 * analysis of 4-way handshake points out that unpredictable nonces
2065 * help in preventing precomputation attacks. Instead of the state
2066 * machine definition, use an unpredictable nonce value here to provide
2067 * stronger protection against potential precomputation attacks.
2068 */
2069 if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) {
Hai Shalomfdcde762020-04-02 11:19:20 -07002070 wpa_printf(MSG_ERROR,
2071 "WPA: Failed to get random data for ANonce.");
Hai Shalome21d4e82020-04-29 16:34:06 -07002072 sm->Disconnect = true;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002073 return;
2074 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002075 wpa_hexdump(MSG_DEBUG, "WPA: Assign ANonce", sm->ANonce,
2076 WPA_NONCE_LEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002077 /* IEEE 802.11i does not clear TimeoutCtr here, but this is more
2078 * logical place than INITIALIZE since AUTHENTICATION2 can be
2079 * re-entered on ReAuthenticationRequest without going through
2080 * INITIALIZE. */
2081 sm->TimeoutCtr = 0;
2082}
2083
2084
Jouni Malinen1420a892017-10-01 12:32:57 +03002085static int wpa_auth_sm_ptk_update(struct wpa_state_machine *sm)
2086{
2087 if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) {
2088 wpa_printf(MSG_ERROR,
2089 "WPA: Failed to get random data for ANonce");
Hai Shalome21d4e82020-04-29 16:34:06 -07002090 sm->Disconnect = true;
Jouni Malinen1420a892017-10-01 12:32:57 +03002091 return -1;
2092 }
2093 wpa_hexdump(MSG_DEBUG, "WPA: Assign new ANonce", sm->ANonce,
2094 WPA_NONCE_LEN);
2095 sm->TimeoutCtr = 0;
2096 return 0;
2097}
2098
2099
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002100SM_STATE(WPA_PTK, INITPMK)
2101{
2102 u8 msk[2 * PMK_LEN];
2103 size_t len = 2 * PMK_LEN;
2104
2105 SM_ENTRY_MA(WPA_PTK, INITPMK, wpa_ptk);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002106#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002107 sm->xxkey_len = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002108#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002109 if (sm->pmksa) {
2110 wpa_printf(MSG_DEBUG, "WPA: PMK from PMKSA cache");
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002111 os_memcpy(sm->PMK, sm->pmksa->pmk, sm->pmksa->pmk_len);
2112 sm->pmk_len = sm->pmksa->pmk_len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002113#ifdef CONFIG_DPP
2114 } else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP) {
2115 wpa_printf(MSG_DEBUG,
2116 "DPP: No PMKSA cache entry for STA - reject connection");
Hai Shalome21d4e82020-04-29 16:34:06 -07002117 sm->Disconnect = true;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002118 sm->disconnect_reason = WLAN_REASON_INVALID_PMKID;
2119 return;
2120#endif /* CONFIG_DPP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002121 } else if (wpa_auth_get_msk(sm->wpa_auth, sm->addr, msk, &len) == 0) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002122 unsigned int pmk_len;
2123
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002124 if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002125 pmk_len = PMK_LEN_SUITE_B_192;
2126 else
2127 pmk_len = PMK_LEN;
Hai Shalomfdcde762020-04-02 11:19:20 -07002128 wpa_printf(MSG_DEBUG,
2129 "WPA: PMK from EAPOL state machine (MSK len=%zu PMK len=%u)",
2130 len, pmk_len);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002131 if (len < pmk_len) {
2132 wpa_printf(MSG_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07002133 "WPA: MSK not long enough (%zu) to create PMK (%u)",
2134 len, pmk_len);
Hai Shalome21d4e82020-04-29 16:34:06 -07002135 sm->Disconnect = true;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002136 return;
2137 }
2138 os_memcpy(sm->PMK, msk, pmk_len);
2139 sm->pmk_len = pmk_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002140#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002141 if (len >= 2 * PMK_LEN) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002142 if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) {
2143 os_memcpy(sm->xxkey, msk, SHA384_MAC_LEN);
2144 sm->xxkey_len = SHA384_MAC_LEN;
2145 } else {
2146 os_memcpy(sm->xxkey, msk + PMK_LEN, PMK_LEN);
2147 sm->xxkey_len = PMK_LEN;
2148 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002149 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002150#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002151 } else {
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002152 wpa_printf(MSG_DEBUG, "WPA: Could not get PMK, get_msk: %p",
Paul Stewart092955c2017-02-06 09:13:09 -08002153 sm->wpa_auth->cb->get_msk);
Hai Shalome21d4e82020-04-29 16:34:06 -07002154 sm->Disconnect = true;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002155 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002156 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002157 forced_memzero(msk, sizeof(msk));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002158
2159 sm->req_replay_counter_used = 0;
Hai Shalome21d4e82020-04-29 16:34:06 -07002160 /* IEEE 802.11i does not set keyRun to false, but not doing this
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002161 * will break reauthentication since EAPOL state machines may not be
2162 * get into AUTHENTICATING state that clears keyRun before WPA state
2163 * machine enters AUTHENTICATION2 state and goes immediately to INITPMK
2164 * state and takes PMK from the previously used AAA Key. This will
2165 * eventually fail in 4-Way Handshake because Supplicant uses PMK
Hai Shalome21d4e82020-04-29 16:34:06 -07002166 * derived from the new AAA Key. Setting keyRun = false here seems to
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002167 * be good workaround for this issue. */
Hai Shalome21d4e82020-04-29 16:34:06 -07002168 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyRun, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002169}
2170
2171
2172SM_STATE(WPA_PTK, INITPSK)
2173{
2174 const u8 *psk;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002175 size_t psk_len;
2176
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002177 SM_ENTRY_MA(WPA_PTK, INITPSK, wpa_ptk);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002178 psk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr, NULL,
Hai Shalom021b0b52019-04-10 11:17:58 -07002179 &psk_len, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002180 if (psk) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002181 os_memcpy(sm->PMK, psk, psk_len);
2182 sm->pmk_len = psk_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002183#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002184 os_memcpy(sm->xxkey, psk, PMK_LEN);
2185 sm->xxkey_len = PMK_LEN;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002186#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002187 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002188#ifdef CONFIG_SAE
2189 if (wpa_auth_uses_sae(sm) && sm->pmksa) {
2190 wpa_printf(MSG_DEBUG, "SAE: PMK from PMKSA cache");
2191 os_memcpy(sm->PMK, sm->pmksa->pmk, sm->pmksa->pmk_len);
2192 sm->pmk_len = sm->pmksa->pmk_len;
Hai Shalom021b0b52019-04-10 11:17:58 -07002193#ifdef CONFIG_IEEE80211R_AP
2194 os_memcpy(sm->xxkey, sm->pmksa->pmk, sm->pmksa->pmk_len);
2195 sm->xxkey_len = sm->pmksa->pmk_len;
2196#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002197 }
2198#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002199 sm->req_replay_counter_used = 0;
2200}
2201
2202
2203SM_STATE(WPA_PTK, PTKSTART)
2204{
2205 u8 buf[2 + RSN_SELECTOR_LEN + PMKID_LEN], *pmkid = NULL;
2206 size_t pmkid_len = 0;
2207
2208 SM_ENTRY_MA(WPA_PTK, PTKSTART, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07002209 sm->PTKRequest = false;
2210 sm->TimeoutEvt = false;
2211 sm->alt_snonce_valid = false;
Sunil Ravia04bd252022-05-02 22:54:18 -07002212 sm->ptkstart_without_success++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002213
2214 sm->TimeoutCtr++;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002215 if (sm->TimeoutCtr > sm->wpa_auth->conf.wpa_pairwise_update_count) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002216 /* No point in sending the EAPOL-Key - we will disconnect
2217 * immediately following this. */
2218 return;
2219 }
2220
2221 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
2222 "sending 1/4 msg of 4-Way Handshake");
2223 /*
Hai Shalomce48b4a2018-09-05 11:41:35 -07002224 * For infrastructure BSS cases, it is better for the AP not to include
2225 * the PMKID KDE in EAPOL-Key msg 1/4 since it could be used to initiate
2226 * offline search for the passphrase/PSK without having to be able to
2227 * capture a 4-way handshake from a STA that has access to the network.
2228 *
2229 * For IBSS cases, addition of PMKID KDE could be considered even with
2230 * WPA2-PSK cases that use multiple PSKs, but only if there is a single
2231 * possible PSK for this STA. However, this should not be done unless
2232 * there is support for using that information on the supplicant side.
2233 * The concern about exposing PMKID unnecessarily in infrastructure BSS
2234 * cases would also apply here, but at least in the IBSS case, this
2235 * would cover a potential real use case.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002236 */
2237 if (sm->wpa == WPA_VERSION_WPA2 &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002238 (wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) ||
2239 (sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE && sm->pmksa) ||
2240 wpa_key_mgmt_sae(sm->wpa_key_mgmt)) &&
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002241 sm->wpa_key_mgmt != WPA_KEY_MGMT_OSEN) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002242 pmkid = buf;
2243 pmkid_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN;
2244 pmkid[0] = WLAN_EID_VENDOR_SPECIFIC;
2245 pmkid[1] = RSN_SELECTOR_LEN + PMKID_LEN;
2246 RSN_SELECTOR_PUT(&pmkid[2], RSN_KEY_DATA_PMKID);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002247 if (sm->pmksa) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002248 wpa_hexdump(MSG_DEBUG,
2249 "RSN: Message 1/4 PMKID from PMKSA entry",
2250 sm->pmksa->pmkid, PMKID_LEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002251 os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN],
2252 sm->pmksa->pmkid, PMKID_LEN);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002253 } else if (wpa_key_mgmt_suite_b(sm->wpa_key_mgmt)) {
2254 /* No KCK available to derive PMKID */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002255 wpa_printf(MSG_DEBUG,
2256 "RSN: No KCK available to derive PMKID for message 1/4");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002257 pmkid = NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -07002258#ifdef CONFIG_FILS
2259 } else if (wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
2260 if (sm->pmkid_set) {
2261 wpa_hexdump(MSG_DEBUG,
2262 "RSN: Message 1/4 PMKID from FILS/ERP",
2263 sm->pmkid, PMKID_LEN);
2264 os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN],
2265 sm->pmkid, PMKID_LEN);
2266 } else {
2267 /* No PMKID available */
2268 wpa_printf(MSG_DEBUG,
2269 "RSN: No FILS/ERP PMKID available for message 1/4");
2270 pmkid = NULL;
2271 }
2272#endif /* CONFIG_FILS */
2273#ifdef CONFIG_IEEE80211R_AP
2274 } else if (wpa_key_mgmt_ft(sm->wpa_key_mgmt) &&
2275 sm->ft_completed) {
2276 wpa_printf(MSG_DEBUG,
2277 "FT: No PMKID in message 1/4 when using FT protocol");
2278 pmkid = NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -07002279#endif /* CONFIG_IEEE80211R_AP */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002280#ifdef CONFIG_SAE
2281 } else if (wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
2282 if (sm->pmkid_set) {
2283 wpa_hexdump(MSG_DEBUG,
2284 "RSN: Message 1/4 PMKID from SAE",
2285 sm->pmkid, PMKID_LEN);
2286 os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN],
2287 sm->pmkid, PMKID_LEN);
2288 } else {
2289 /* No PMKID available */
2290 wpa_printf(MSG_DEBUG,
2291 "RSN: No SAE PMKID available for message 1/4");
2292 pmkid = NULL;
2293 }
2294#endif /* CONFIG_SAE */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002295 } else {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002296 /*
2297 * Calculate PMKID since no PMKSA cache entry was
2298 * available with pre-calculated PMKID.
2299 */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002300 rsn_pmkid(sm->PMK, sm->pmk_len, sm->wpa_auth->addr,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002301 sm->addr, &pmkid[2 + RSN_SELECTOR_LEN],
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002302 sm->wpa_key_mgmt);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002303 wpa_hexdump(MSG_DEBUG,
2304 "RSN: Message 1/4 PMKID derived from PMK",
2305 &pmkid[2 + RSN_SELECTOR_LEN], PMKID_LEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002306 }
2307 }
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002308 if (!pmkid)
2309 pmkid_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002310 wpa_send_eapol(sm->wpa_auth, sm,
2311 WPA_KEY_INFO_ACK | WPA_KEY_INFO_KEY_TYPE, NULL,
2312 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 }
Hai Shalome21d4e82020-04-29 16:34:06 -07002895 sm->tk_already_set = true;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002896
Hai Shalom60840252021-02-19 19:02:11 -08002897 wpa_auth_store_ptksa(sm->wpa_auth, sm->addr, sm->pairwise,
2898 dot11RSNAConfigPMKLifetime, &sm->PTK);
2899
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002900 return 0;
2901}
2902
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002903
2904u8 * hostapd_eid_assoc_fils_session(struct wpa_state_machine *sm, u8 *buf,
2905 const u8 *fils_session, struct wpabuf *hlp)
2906{
2907 struct wpabuf *plain;
2908 u8 *pos = buf;
2909
2910 /* FILS Session */
2911 *pos++ = WLAN_EID_EXTENSION; /* Element ID */
2912 *pos++ = 1 + FILS_SESSION_LEN; /* Length */
2913 *pos++ = WLAN_EID_EXT_FILS_SESSION; /* Element ID Extension */
2914 os_memcpy(pos, fils_session, FILS_SESSION_LEN);
2915 pos += FILS_SESSION_LEN;
2916
2917 plain = fils_prepare_plainbuf(sm, hlp);
2918 if (!plain) {
2919 wpa_printf(MSG_DEBUG, "FILS: Plain buffer prep failed");
2920 return NULL;
2921 }
2922
2923 os_memcpy(pos, wpabuf_head(plain), wpabuf_len(plain));
2924 pos += wpabuf_len(plain);
2925
Hai Shalomfdcde762020-04-02 11:19:20 -07002926 wpa_printf(MSG_DEBUG, "%s: plain buf_len: %zu", __func__,
2927 wpabuf_len(plain));
Hai Shalom81f62d82019-07-22 12:10:00 -07002928 wpabuf_clear_free(plain);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002929 sm->fils_completed = 1;
2930 return pos;
2931}
2932
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002933#endif /* CONFIG_FILS */
2934
2935
Hai Shalom74f70d42019-02-11 14:42:39 -08002936#ifdef CONFIG_OCV
2937int get_sta_tx_parameters(struct wpa_state_machine *sm, int ap_max_chanwidth,
2938 int ap_seg1_idx, int *bandwidth, int *seg1_idx)
2939{
2940 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
2941
2942 if (!wpa_auth->cb->get_sta_tx_params)
2943 return -1;
2944 return wpa_auth->cb->get_sta_tx_params(wpa_auth->cb_ctx, sm->addr,
2945 ap_max_chanwidth, ap_seg1_idx,
2946 bandwidth, seg1_idx);
2947}
2948#endif /* CONFIG_OCV */
2949
2950
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002951SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
2952{
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002953 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002954 struct wpa_ptk PTK;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07002955 int ok = 0, psk_found = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002956 const u8 *pmk = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002957 size_t pmk_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002958 int ft;
2959 const u8 *eapol_key_ie, *key_data, *mic;
2960 u16 key_data_length;
2961 size_t mic_len, eapol_key_ie_len;
2962 struct ieee802_1x_hdr *hdr;
2963 struct wpa_eapol_key *key;
2964 struct wpa_eapol_ie_parse kde;
Hai Shalom021b0b52019-04-10 11:17:58 -07002965 int vlan_id = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002966 int owe_ptk_workaround = !!wpa_auth->conf.owe_ptk_workaround;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002967
2968 SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07002969 sm->EAPOLKeyReceived = false;
2970 sm->update_snonce = false;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002971 os_memset(&PTK, 0, sizeof(PTK));
2972
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002973 mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002974
2975 /* WPA with IEEE 802.1X: use the derived PMK from EAP
2976 * WPA-PSK: iterate through possible PSKs and select the one matching
2977 * the packet */
2978 for (;;) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002979 if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
2980 !wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002981 pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr,
Hai Shalom021b0b52019-04-10 11:17:58 -07002982 sm->p2p_dev_addr, pmk, &pmk_len,
2983 &vlan_id);
Hai Shalomfdcde762020-04-02 11:19:20 -07002984 if (!pmk)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002985 break;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07002986 psk_found = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002987#ifdef CONFIG_IEEE80211R_AP
2988 if (wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) {
2989 os_memcpy(sm->xxkey, pmk, pmk_len);
2990 sm->xxkey_len = pmk_len;
2991 }
2992#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002993 } else {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002994 pmk = sm->PMK;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002995 pmk_len = sm->pmk_len;
2996 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002997
Hai Shalom81f62d82019-07-22 12:10:00 -07002998 if ((!pmk || !pmk_len) && sm->pmksa) {
2999 wpa_printf(MSG_DEBUG, "WPA: Use PMK from PMKSA cache");
3000 pmk = sm->pmksa->pmk;
3001 pmk_len = sm->pmksa->pmk_len;
3002 }
3003
Hai Shalomfdcde762020-04-02 11:19:20 -07003004 if (wpa_derive_ptk(sm, sm->SNonce, pmk, pmk_len, &PTK,
3005 owe_ptk_workaround == 2) < 0)
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003006 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003007
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003008 if (mic_len &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003009 wpa_verify_key_mic(sm->wpa_key_mgmt, pmk_len, &PTK,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003010 sm->last_rx_eapol_key,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003011 sm->last_rx_eapol_key_len) == 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07003012 if (sm->PMK != pmk) {
3013 os_memcpy(sm->PMK, pmk, pmk_len);
3014 sm->pmk_len = pmk_len;
3015 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003016 ok = 1;
3017 break;
3018 }
3019
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003020#ifdef CONFIG_FILS
3021 if (!mic_len &&
3022 wpa_aead_decrypt(sm, &PTK, sm->last_rx_eapol_key,
3023 sm->last_rx_eapol_key_len, NULL) == 0) {
3024 ok = 1;
3025 break;
3026 }
3027#endif /* CONFIG_FILS */
3028
Hai Shalomfdcde762020-04-02 11:19:20 -07003029#ifdef CONFIG_OWE
3030 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE && pmk_len > 32 &&
3031 owe_ptk_workaround == 1) {
3032 wpa_printf(MSG_DEBUG,
3033 "OWE: Try PTK derivation workaround with SHA256");
3034 owe_ptk_workaround = 2;
3035 continue;
3036 }
3037#endif /* CONFIG_OWE */
3038
Roshan Pius3a1667e2018-07-03 15:17:14 -07003039 if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
3040 wpa_key_mgmt_sae(sm->wpa_key_mgmt))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003041 break;
3042 }
3043
Sunil Ravia04bd252022-05-02 22:54:18 -07003044 if (!ok && wpa_key_mgmt_wpa_psk_no_sae(sm->wpa_key_mgmt) &&
3045 wpa_auth->conf.radius_psk && wpa_auth->cb->request_radius_psk &&
3046 !sm->waiting_radius_psk) {
3047 wpa_printf(MSG_DEBUG, "No PSK available - ask RADIUS server");
3048 wpa_auth->cb->request_radius_psk(wpa_auth->cb_ctx, sm->addr,
3049 sm->wpa_key_mgmt,
3050 sm->ANonce,
3051 sm->last_rx_eapol_key,
3052 sm->last_rx_eapol_key_len);
3053 sm->waiting_radius_psk = 1;
3054 return;
3055 }
3056
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003057 if (!ok) {
3058 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
3059 "invalid MIC in msg 2/4 of 4-Way Handshake");
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07003060 if (psk_found)
3061 wpa_auth_psk_failure_report(sm->wpa_auth, sm->addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003062 return;
3063 }
3064
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003065 /*
3066 * Note: last_rx_eapol_key length fields have already been validated in
3067 * wpa_receive().
3068 */
3069 hdr = (struct ieee802_1x_hdr *) sm->last_rx_eapol_key;
3070 key = (struct wpa_eapol_key *) (hdr + 1);
3071 mic = (u8 *) (key + 1);
3072 key_data = mic + mic_len + 2;
3073 key_data_length = WPA_GET_BE16(mic + mic_len);
3074 if (key_data_length > sm->last_rx_eapol_key_len - sizeof(*hdr) -
3075 sizeof(*key) - mic_len - 2)
3076 return;
3077
3078 if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) {
3079 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
3080 "received EAPOL-Key msg 2/4 with invalid Key Data contents");
3081 return;
3082 }
3083 if (kde.rsn_ie) {
3084 eapol_key_ie = kde.rsn_ie;
3085 eapol_key_ie_len = kde.rsn_ie_len;
3086 } else if (kde.osen) {
3087 eapol_key_ie = kde.osen;
3088 eapol_key_ie_len = kde.osen_len;
3089 } else {
3090 eapol_key_ie = kde.wpa_ie;
3091 eapol_key_ie_len = kde.wpa_ie_len;
3092 }
3093 ft = sm->wpa == WPA_VERSION_WPA2 && wpa_key_mgmt_ft(sm->wpa_key_mgmt);
Hai Shalomfdcde762020-04-02 11:19:20 -07003094 if (!sm->wpa_ie ||
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003095 wpa_compare_rsn_ie(ft, sm->wpa_ie, sm->wpa_ie_len,
3096 eapol_key_ie, eapol_key_ie_len)) {
3097 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
3098 "WPA IE from (Re)AssocReq did not match with msg 2/4");
3099 if (sm->wpa_ie) {
3100 wpa_hexdump(MSG_DEBUG, "WPA IE in AssocReq",
3101 sm->wpa_ie, sm->wpa_ie_len);
3102 }
3103 wpa_hexdump(MSG_DEBUG, "WPA IE in msg 2/4",
3104 eapol_key_ie, eapol_key_ie_len);
3105 /* MLME-DEAUTHENTICATE.request */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003106 wpa_sta_disconnect(wpa_auth, sm->addr,
3107 WLAN_REASON_PREV_AUTH_NOT_VALID);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003108 return;
3109 }
Hai Shalomc3565922019-10-28 11:58:20 -07003110 if ((!sm->rsnxe && kde.rsnxe) ||
3111 (sm->rsnxe && !kde.rsnxe) ||
3112 (sm->rsnxe && kde.rsnxe &&
3113 (sm->rsnxe_len != kde.rsnxe_len ||
3114 os_memcmp(sm->rsnxe, kde.rsnxe, sm->rsnxe_len) != 0))) {
3115 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
3116 "RSNXE from (Re)AssocReq did not match the one in EAPOL-Key msg 2/4");
3117 wpa_hexdump(MSG_DEBUG, "RSNXE in AssocReq",
3118 sm->rsnxe, sm->rsnxe_len);
3119 wpa_hexdump(MSG_DEBUG, "RSNXE in EAPOL-Key msg 2/4",
3120 kde.rsnxe, kde.rsnxe_len);
3121 /* MLME-DEAUTHENTICATE.request */
3122 wpa_sta_disconnect(wpa_auth, sm->addr,
3123 WLAN_REASON_PREV_AUTH_NOT_VALID);
3124 return;
3125 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003126#ifdef CONFIG_OCV
3127 if (wpa_auth_uses_ocv(sm)) {
3128 struct wpa_channel_info ci;
3129 int tx_chanwidth;
3130 int tx_seg1_idx;
Hai Shalom899fcc72020-10-19 14:38:18 -07003131 enum oci_verify_result res;
Hai Shalom74f70d42019-02-11 14:42:39 -08003132
3133 if (wpa_channel_info(wpa_auth, &ci) != 0) {
3134 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
3135 "Failed to get channel info to validate received OCI in EAPOL-Key 2/4");
3136 return;
3137 }
3138
3139 if (get_sta_tx_parameters(sm,
3140 channel_width_to_int(ci.chanwidth),
3141 ci.seg1_idx, &tx_chanwidth,
3142 &tx_seg1_idx) < 0)
3143 return;
3144
Hai Shalom899fcc72020-10-19 14:38:18 -07003145 res = ocv_verify_tx_params(kde.oci, kde.oci_len, &ci,
3146 tx_chanwidth, tx_seg1_idx);
3147 if (wpa_auth_uses_ocv(sm) == 2 && res == OCI_NOT_FOUND) {
3148 /* Work around misbehaving STAs */
3149 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
3150 "Disable OCV with a STA that does not send OCI");
3151 wpa_auth_set_ocv(sm, 0);
3152 } else if (res != OCI_SUCCESS) {
3153 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
3154 "OCV failed: %s", ocv_errorstr);
3155 if (wpa_auth->conf.msg_ctx)
3156 wpa_msg(wpa_auth->conf.msg_ctx, MSG_INFO,
3157 OCV_FAILURE "addr=" MACSTR
3158 " frame=eapol-key-m2 error=%s",
3159 MAC2STR(sm->addr), ocv_errorstr);
Hai Shalom74f70d42019-02-11 14:42:39 -08003160 return;
3161 }
3162 }
3163#endif /* CONFIG_OCV */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003164#ifdef CONFIG_IEEE80211R_AP
3165 if (ft && ft_check_msg_2_of_4(wpa_auth, sm, &kde) < 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003166 wpa_sta_disconnect(wpa_auth, sm->addr,
3167 WLAN_REASON_PREV_AUTH_NOT_VALID);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003168 return;
3169 }
3170#endif /* CONFIG_IEEE80211R_AP */
3171#ifdef CONFIG_P2P
3172 if (kde.ip_addr_req && kde.ip_addr_req[0] &&
3173 wpa_auth->ip_pool && WPA_GET_BE32(sm->ip_addr) == 0) {
3174 int idx;
3175 wpa_printf(MSG_DEBUG,
3176 "P2P: IP address requested in EAPOL-Key exchange");
3177 idx = bitfield_get_first_zero(wpa_auth->ip_pool);
3178 if (idx >= 0) {
3179 u32 start = WPA_GET_BE32(wpa_auth->conf.ip_addr_start);
3180 bitfield_set(wpa_auth->ip_pool, idx);
3181 WPA_PUT_BE32(sm->ip_addr, start + idx);
3182 wpa_printf(MSG_DEBUG,
3183 "P2P: Assigned IP address %u.%u.%u.%u to "
3184 MACSTR, sm->ip_addr[0], sm->ip_addr[1],
3185 sm->ip_addr[2], sm->ip_addr[3],
3186 MAC2STR(sm->addr));
3187 }
3188 }
3189#endif /* CONFIG_P2P */
3190
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003191#ifdef CONFIG_DPP2
3192 if (DPP_VERSION > 1 && kde.dpp_kde) {
3193 wpa_printf(MSG_DEBUG,
3194 "DPP: peer Protocol Version %u Flags 0x%x",
3195 kde.dpp_kde[0], kde.dpp_kde[1]);
3196 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP &&
3197 wpa_auth->conf.dpp_pfs != 2 &&
3198 (kde.dpp_kde[1] & DPP_KDE_PFS_ALLOWED) &&
3199 !sm->dpp_z) {
3200 wpa_printf(MSG_INFO,
3201 "DPP: Peer indicated it supports PFS and local configuration allows this, but PFS was not negotiated for the association");
3202 wpa_sta_disconnect(wpa_auth, sm->addr,
3203 WLAN_REASON_PREV_AUTH_NOT_VALID);
3204 return;
3205 }
3206 }
3207#endif /* CONFIG_DPP2 */
3208
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003209#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003210 if (sm->wpa == WPA_VERSION_WPA2 && wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
3211 /*
3212 * Verify that PMKR1Name from EAPOL-Key message 2/4 matches
3213 * with the value we derived.
3214 */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003215 if (os_memcmp_const(sm->sup_pmk_r1_name, sm->pmk_r1_name,
3216 WPA_PMK_NAME_LEN) != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003217 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07003218 "PMKR1Name mismatch in FT 4-way handshake");
3219 wpa_hexdump(MSG_DEBUG,
3220 "FT: PMKR1Name from Supplicant",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003221 sm->sup_pmk_r1_name, WPA_PMK_NAME_LEN);
3222 wpa_hexdump(MSG_DEBUG, "FT: Derived PMKR1Name",
3223 sm->pmk_r1_name, WPA_PMK_NAME_LEN);
3224 return;
3225 }
3226 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003227#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003228
Hai Shalom021b0b52019-04-10 11:17:58 -07003229 if (vlan_id && wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
3230 wpa_auth_update_vlan(wpa_auth, sm->addr, vlan_id) < 0) {
3231 wpa_sta_disconnect(wpa_auth, sm->addr,
3232 WLAN_REASON_PREV_AUTH_NOT_VALID);
3233 return;
3234 }
3235
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003236 sm->pending_1_of_4_timeout = 0;
3237 eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm);
3238
Hai Shalom60840252021-02-19 19:02:11 -08003239 if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) && sm->PMK != pmk) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003240 /* PSK may have changed from the previous choice, so update
3241 * state machine data based on whatever PSK was selected here.
3242 */
3243 os_memcpy(sm->PMK, pmk, PMK_LEN);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003244 sm->pmk_len = PMK_LEN;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003245 }
3246
Hai Shalome21d4e82020-04-29 16:34:06 -07003247 sm->MICVerified = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003248
3249 os_memcpy(&sm->PTK, &PTK, sizeof(PTK));
Hai Shalom81f62d82019-07-22 12:10:00 -07003250 forced_memzero(&PTK, sizeof(PTK));
Hai Shalome21d4e82020-04-29 16:34:06 -07003251 sm->PTK_valid = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003252}
3253
3254
3255SM_STATE(WPA_PTK, PTKCALCNEGOTIATING2)
3256{
3257 SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING2, wpa_ptk);
3258 sm->TimeoutCtr = 0;
3259}
3260
3261
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003262static int ieee80211w_kde_len(struct wpa_state_machine *sm)
3263{
Hai Shalomfdcde762020-04-02 11:19:20 -07003264 size_t len = 0;
3265
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003266 if (sm->mgmt_frame_prot) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003267 len += 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN;
3268 len += wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
3269 }
3270 if (sm->mgmt_frame_prot && sm->wpa_auth->conf.beacon_prot) {
3271 len += 2 + RSN_SELECTOR_LEN + WPA_BIGTK_KDE_PREFIX_LEN;
3272 len += wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003273 }
3274
Hai Shalomfdcde762020-04-02 11:19:20 -07003275 return len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003276}
3277
3278
3279static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos)
3280{
3281 struct wpa_igtk_kde igtk;
Hai Shalomfdcde762020-04-02 11:19:20 -07003282 struct wpa_bigtk_kde bigtk;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003283 struct wpa_group *gsm = sm->group;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003284 u8 rsc[WPA_KEY_RSC_LEN];
Hai Shalomfdcde762020-04-02 11:19:20 -07003285 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
3286 size_t len = wpa_cipher_key_len(conf->group_mgmt_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003287
3288 if (!sm->mgmt_frame_prot)
3289 return pos;
3290
3291 igtk.keyid[0] = gsm->GN_igtk;
3292 igtk.keyid[1] = 0;
3293 if (gsm->wpa_group_state != WPA_GROUP_SETKEYSDONE ||
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003294 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, rsc) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003295 os_memset(igtk.pn, 0, sizeof(igtk.pn));
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003296 else
3297 os_memcpy(igtk.pn, rsc, sizeof(igtk.pn));
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003298 os_memcpy(igtk.igtk, gsm->IGTK[gsm->GN_igtk - 4], len);
Hai Shalomfdcde762020-04-02 11:19:20 -07003299 if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003300 /*
3301 * Provide unique random IGTK to each STA to prevent use of
3302 * IGTK in the BSS.
3303 */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003304 if (random_get_bytes(igtk.igtk, len) < 0)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003305 return pos;
3306 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003307 pos = wpa_add_kde(pos, RSN_KEY_DATA_IGTK,
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003308 (const u8 *) &igtk, WPA_IGTK_KDE_PREFIX_LEN + len,
3309 NULL, 0);
Sunil Ravia04bd252022-05-02 22:54:18 -07003310 forced_memzero(&igtk, sizeof(igtk));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003311
Hai Shalomfdcde762020-04-02 11:19:20 -07003312 if (!conf->beacon_prot)
3313 return pos;
3314
3315 bigtk.keyid[0] = gsm->GN_bigtk;
3316 bigtk.keyid[1] = 0;
3317 if (gsm->wpa_group_state != WPA_GROUP_SETKEYSDONE ||
3318 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_bigtk, rsc) < 0)
3319 os_memset(bigtk.pn, 0, sizeof(bigtk.pn));
3320 else
3321 os_memcpy(bigtk.pn, rsc, sizeof(bigtk.pn));
3322 os_memcpy(bigtk.bigtk, gsm->BIGTK[gsm->GN_bigtk - 6], len);
Hai Shalom899fcc72020-10-19 14:38:18 -07003323 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
3324 /*
3325 * Provide unique random BIGTK to each OSEN STA to prevent use
3326 * of BIGTK in the BSS.
3327 */
3328 if (random_get_bytes(bigtk.bigtk, len) < 0)
3329 return pos;
3330 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003331 pos = wpa_add_kde(pos, RSN_KEY_DATA_BIGTK,
3332 (const u8 *) &bigtk, WPA_BIGTK_KDE_PREFIX_LEN + len,
3333 NULL, 0);
Sunil Ravia04bd252022-05-02 22:54:18 -07003334 forced_memzero(&bigtk, sizeof(bigtk));
Hai Shalomfdcde762020-04-02 11:19:20 -07003335
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003336 return pos;
3337}
3338
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003339
Hai Shalom74f70d42019-02-11 14:42:39 -08003340static int ocv_oci_len(struct wpa_state_machine *sm)
3341{
3342#ifdef CONFIG_OCV
3343 if (wpa_auth_uses_ocv(sm))
3344 return OCV_OCI_KDE_LEN;
3345#endif /* CONFIG_OCV */
3346 return 0;
3347}
3348
Hai Shalom899fcc72020-10-19 14:38:18 -07003349
3350static int ocv_oci_add(struct wpa_state_machine *sm, u8 **argpos,
3351 unsigned int freq)
Hai Shalom74f70d42019-02-11 14:42:39 -08003352{
3353#ifdef CONFIG_OCV
3354 struct wpa_channel_info ci;
3355
3356 if (!wpa_auth_uses_ocv(sm))
3357 return 0;
3358
3359 if (wpa_channel_info(sm->wpa_auth, &ci) != 0) {
3360 wpa_printf(MSG_WARNING,
3361 "Failed to get channel info for OCI element");
3362 return -1;
3363 }
Hai Shalom899fcc72020-10-19 14:38:18 -07003364#ifdef CONFIG_TESTING_OPTIONS
3365 if (freq) {
3366 wpa_printf(MSG_INFO,
3367 "TEST: Override OCI KDE frequency %d -> %u MHz",
3368 ci.frequency, freq);
3369 ci.frequency = freq;
3370 }
3371#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom74f70d42019-02-11 14:42:39 -08003372
3373 return ocv_insert_oci_kde(&ci, argpos);
3374#else /* CONFIG_OCV */
3375 return 0;
3376#endif /* CONFIG_OCV */
3377}
3378
3379
Hai Shalomfdcde762020-04-02 11:19:20 -07003380#ifdef CONFIG_TESTING_OPTIONS
3381static u8 * replace_ie(const char *name, const u8 *old_buf, size_t *len, u8 eid,
3382 const u8 *ie, size_t ie_len)
3383{
3384 const u8 *elem;
3385 u8 *buf;
3386
3387 wpa_printf(MSG_DEBUG, "TESTING: %s EAPOL override", name);
3388 wpa_hexdump(MSG_DEBUG, "TESTING: wpa_ie before override",
3389 old_buf, *len);
3390 buf = os_malloc(*len + ie_len);
3391 if (!buf)
3392 return NULL;
3393 os_memcpy(buf, old_buf, *len);
3394 elem = get_ie(buf, *len, eid);
3395 if (elem) {
3396 u8 elem_len = 2 + elem[1];
3397
3398 os_memmove((void *) elem, elem + elem_len,
3399 *len - (elem - buf) - elem_len);
3400 *len -= elem_len;
3401 }
3402 os_memcpy(buf + *len, ie, ie_len);
3403 *len += ie_len;
3404 wpa_hexdump(MSG_DEBUG, "TESTING: wpa_ie after EAPOL override",
3405 buf, *len);
3406
3407 return buf;
3408}
3409#endif /* CONFIG_TESTING_OPTIONS */
3410
3411
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003412SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
3413{
Hai Shaloma20dcd72022-02-04 13:43:00 -08003414 u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde = NULL, *pos, stub_gtk[32];
Sunil Ravia04bd252022-05-02 22:54:18 -07003415 size_t gtk_len, kde_len = 0, wpa_ie_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003416 struct wpa_group *gsm = sm->group;
3417 u8 *wpa_ie;
Hai Shalomfdcde762020-04-02 11:19:20 -07003418 int secure, gtkidx, encr = 0;
3419 u8 *wpa_ie_buf = NULL, *wpa_ie_buf2 = NULL;
3420 u8 hdr[2];
3421 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003422
3423 SM_ENTRY_MA(WPA_PTK, PTKINITNEGOTIATING, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07003424 sm->TimeoutEvt = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003425
3426 sm->TimeoutCtr++;
Hai Shalomfdcde762020-04-02 11:19:20 -07003427 if (conf->wpa_disable_eapol_key_retries && sm->TimeoutCtr > 1) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003428 /* Do not allow retransmission of EAPOL-Key msg 3/4 */
3429 return;
3430 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003431 if (sm->TimeoutCtr > conf->wpa_pairwise_update_count) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003432 /* No point in sending the EAPOL-Key - we will disconnect
3433 * immediately following this. */
3434 return;
3435 }
3436
3437 /* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, [MDIE],
Hai Shalomfdcde762020-04-02 11:19:20 -07003438 GTK[GN], IGTK, [BIGTK], [FTIE], [TIE * 2])
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003439 */
3440 os_memset(rsc, 0, WPA_KEY_RSC_LEN);
3441 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc);
3442 /* If FT is used, wpa_auth->wpa_ie includes both RSNIE and MDIE */
3443 wpa_ie = sm->wpa_auth->wpa_ie;
3444 wpa_ie_len = sm->wpa_auth->wpa_ie_len;
Hai Shalomfdcde762020-04-02 11:19:20 -07003445 if (sm->wpa == WPA_VERSION_WPA && (conf->wpa & WPA_PROTO_RSN) &&
3446 wpa_ie_len > wpa_ie[1] + 2U && wpa_ie[0] == WLAN_EID_RSN) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003447 /* WPA-only STA, remove RSN IE and possible MDIE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003448 wpa_ie = wpa_ie + wpa_ie[1] + 2;
Hai Shalom60840252021-02-19 19:02:11 -08003449 if (wpa_ie[0] == WLAN_EID_RSNX)
3450 wpa_ie = wpa_ie + wpa_ie[1] + 2;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003451 if (wpa_ie[0] == WLAN_EID_MOBILITY_DOMAIN)
3452 wpa_ie = wpa_ie + wpa_ie[1] + 2;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003453 wpa_ie_len = wpa_ie[1] + 2;
3454 }
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003455#ifdef CONFIG_TESTING_OPTIONS
Hai Shalomfdcde762020-04-02 11:19:20 -07003456 if (conf->rsne_override_eapol_set) {
3457 wpa_ie_buf2 = replace_ie(
3458 "RSNE", wpa_ie, &wpa_ie_len, WLAN_EID_RSN,
3459 conf->rsne_override_eapol,
3460 conf->rsne_override_eapol_len);
3461 if (!wpa_ie_buf2)
3462 goto done;
3463 wpa_ie = wpa_ie_buf2;
3464 }
3465 if (conf->rsnxe_override_eapol_set) {
3466 wpa_ie_buf = replace_ie(
3467 "RSNXE", wpa_ie, &wpa_ie_len, WLAN_EID_RSNX,
3468 conf->rsnxe_override_eapol,
3469 conf->rsnxe_override_eapol_len);
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003470 if (!wpa_ie_buf)
Hai Shalomfdcde762020-04-02 11:19:20 -07003471 goto done;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003472 wpa_ie = wpa_ie_buf;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003473 }
3474#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003475 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
3476 "sending 3/4 msg of 4-Way Handshake");
3477 if (sm->wpa == WPA_VERSION_WPA2) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003478 if (sm->use_ext_key_id && sm->TimeoutCtr == 1 &&
3479 wpa_auth_set_key(sm->wpa_auth, 0,
3480 wpa_cipher_to_alg(sm->pairwise),
3481 sm->addr,
3482 sm->keyidx_active, sm->PTK.tk,
3483 wpa_cipher_key_len(sm->pairwise),
3484 KEY_FLAG_PAIRWISE_RX)) {
3485 wpa_sta_disconnect(sm->wpa_auth, sm->addr,
3486 WLAN_REASON_PREV_AUTH_NOT_VALID);
3487 return;
3488 }
3489
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003490 /* WPA2 send GTK in the 4-way handshake */
3491 secure = 1;
3492 gtk = gsm->GTK[gsm->GN - 1];
3493 gtk_len = gsm->GTK_len;
Hai Shalomfdcde762020-04-02 11:19:20 -07003494 if (conf->disable_gtk ||
Roshan Pius3a1667e2018-07-03 15:17:14 -07003495 sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003496 /*
3497 * Provide unique random GTK to each STA to prevent use
3498 * of GTK in the BSS.
3499 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003500 if (random_get_bytes(stub_gtk, gtk_len) < 0)
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003501 goto done;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003502 gtk = stub_gtk;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003503 }
Hai Shalomc3565922019-10-28 11:58:20 -07003504 gtkidx = gsm->GN;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003505 _rsc = rsc;
3506 encr = 1;
3507 } else {
3508 /* WPA does not include GTK in msg 3/4 */
3509 secure = 0;
3510 gtk = NULL;
3511 gtk_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003512 _rsc = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003513 if (sm->rx_eapol_key_secure) {
3514 /*
3515 * It looks like Windows 7 supplicant tries to use
3516 * Secure bit in msg 2/4 after having reported Michael
3517 * MIC failure and it then rejects the 4-way handshake
3518 * if msg 3/4 does not set Secure bit. Work around this
3519 * by setting the Secure bit here even in the case of
3520 * WPA if the supplicant used it first.
3521 */
3522 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07003523 "STA used Secure bit in WPA msg 2/4 - set Secure for 3/4 as workaround");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003524 secure = 1;
3525 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003526 }
3527
Hai Shalom74f70d42019-02-11 14:42:39 -08003528 kde_len = wpa_ie_len + ieee80211w_kde_len(sm) + ocv_oci_len(sm);
Hai Shalomfdcde762020-04-02 11:19:20 -07003529
3530 if (sm->use_ext_key_id)
3531 kde_len += 2 + RSN_SELECTOR_LEN + 2;
3532
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003533 if (gtk)
3534 kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003535#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003536 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
3537 kde_len += 2 + PMKID_LEN; /* PMKR1Name into RSN IE */
3538 kde_len += 300; /* FTIE + 2 * TIE */
3539 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003540#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08003541#ifdef CONFIG_P2P
3542 if (WPA_GET_BE32(sm->ip_addr) > 0)
3543 kde_len += 2 + RSN_SELECTOR_LEN + 3 * 4;
3544#endif /* CONFIG_P2P */
Hai Shalomfdcde762020-04-02 11:19:20 -07003545
3546 if (conf->transition_disable)
3547 kde_len += 2 + RSN_SELECTOR_LEN + 1;
3548
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003549#ifdef CONFIG_DPP2
3550 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP)
3551 kde_len += 2 + RSN_SELECTOR_LEN + 2;
3552#endif /* CONFIG_DPP2 */
3553
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003554 kde = os_malloc(kde_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07003555 if (!kde)
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003556 goto done;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003557
3558 pos = kde;
3559 os_memcpy(pos, wpa_ie, wpa_ie_len);
3560 pos += wpa_ie_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003561#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003562 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08003563 int res;
3564 size_t elen;
3565
3566 elen = pos - kde;
3567 res = wpa_insert_pmkid(kde, &elen, sm->pmk_r1_name);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003568 if (res < 0) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003569 wpa_printf(MSG_ERROR,
3570 "FT: Failed to insert PMKR1Name into RSN IE in EAPOL-Key data");
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003571 goto done;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003572 }
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08003573 pos -= wpa_ie_len;
3574 pos += elen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003575 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003576#endif /* CONFIG_IEEE80211R_AP */
Hai Shalomfdcde762020-04-02 11:19:20 -07003577 hdr[1] = 0;
3578
3579 if (sm->use_ext_key_id) {
3580 hdr[0] = sm->keyidx_active & 0x01;
3581 pos = wpa_add_kde(pos, RSN_KEY_DATA_KEYID, hdr, 2, NULL, 0);
3582 }
3583
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003584 if (gtk) {
Hai Shalomc3565922019-10-28 11:58:20 -07003585 hdr[0] = gtkidx & 0x03;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003586 pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
3587 gtk, gtk_len);
3588 }
3589 pos = ieee80211w_kde_add(sm, pos);
Hai Shalom899fcc72020-10-19 14:38:18 -07003590 if (ocv_oci_add(sm, &pos, conf->oci_freq_override_eapol_m3) < 0)
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003591 goto done;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003592
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003593#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003594 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
3595 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003596
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08003597 if (sm->assoc_resp_ftie &&
3598 kde + kde_len - pos >= 2 + sm->assoc_resp_ftie[1]) {
3599 os_memcpy(pos, sm->assoc_resp_ftie,
3600 2 + sm->assoc_resp_ftie[1]);
3601 res = 2 + sm->assoc_resp_ftie[1];
3602 } else {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003603 int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt);
3604
3605 res = wpa_write_ftie(conf, use_sha384,
3606 conf->r0_key_holder,
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08003607 conf->r0_key_holder_len,
3608 NULL, NULL, pos,
3609 kde + kde_len - pos,
Hai Shalomfdcde762020-04-02 11:19:20 -07003610 NULL, 0, 0);
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08003611 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003612 if (res < 0) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003613 wpa_printf(MSG_ERROR,
3614 "FT: Failed to insert FTIE into EAPOL-Key Key Data");
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003615 goto done;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003616 }
3617 pos += res;
3618
3619 /* TIE[ReassociationDeadline] (TU) */
3620 *pos++ = WLAN_EID_TIMEOUT_INTERVAL;
3621 *pos++ = 5;
3622 *pos++ = WLAN_TIMEOUT_REASSOC_DEADLINE;
3623 WPA_PUT_LE32(pos, conf->reassociation_deadline);
3624 pos += 4;
3625
3626 /* TIE[KeyLifetime] (seconds) */
3627 *pos++ = WLAN_EID_TIMEOUT_INTERVAL;
3628 *pos++ = 5;
3629 *pos++ = WLAN_TIMEOUT_KEY_LIFETIME;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003630 WPA_PUT_LE32(pos, conf->r0_key_lifetime);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003631 pos += 4;
3632 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003633#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08003634#ifdef CONFIG_P2P
3635 if (WPA_GET_BE32(sm->ip_addr) > 0) {
3636 u8 addr[3 * 4];
3637 os_memcpy(addr, sm->ip_addr, 4);
Hai Shalomfdcde762020-04-02 11:19:20 -07003638 os_memcpy(addr + 4, conf->ip_addr_mask, 4);
3639 os_memcpy(addr + 8, conf->ip_addr_go, 4);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08003640 pos = wpa_add_kde(pos, WFA_KEY_DATA_IP_ADDR_ALLOC,
3641 addr, sizeof(addr), NULL, 0);
3642 }
3643#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003644
Hai Shalomfdcde762020-04-02 11:19:20 -07003645 if (conf->transition_disable)
3646 pos = wpa_add_kde(pos, WFA_KEY_DATA_TRANSITION_DISABLE,
3647 &conf->transition_disable, 1, NULL, 0);
3648
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003649#ifdef CONFIG_DPP2
3650 if (DPP_VERSION > 1 && sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP) {
3651 u8 payload[2];
3652
3653 payload[0] = DPP_VERSION; /* Protocol Version */
3654 payload[1] = 0; /* Flags */
3655 if (conf->dpp_pfs == 0)
3656 payload[1] |= DPP_KDE_PFS_ALLOWED;
3657 else if (conf->dpp_pfs == 1)
3658 payload[1] |= DPP_KDE_PFS_ALLOWED |
3659 DPP_KDE_PFS_REQUIRED;
3660 pos = wpa_add_kde(pos, WFA_KEY_DATA_DPP,
3661 payload, sizeof(payload), NULL, 0);
3662 }
3663#endif /* CONFIG_DPP2 */
3664
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003665 wpa_send_eapol(sm->wpa_auth, sm,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003666 (secure ? WPA_KEY_INFO_SECURE : 0) |
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003667 (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
3668 WPA_KEY_INFO_MIC : 0) |
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003669 WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL |
3670 WPA_KEY_INFO_KEY_TYPE,
Hai Shalomc3565922019-10-28 11:58:20 -07003671 _rsc, sm->ANonce, kde, pos - kde, 0, encr);
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003672done:
Sunil Ravia04bd252022-05-02 22:54:18 -07003673 bin_clear_free(kde, kde_len);
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003674 os_free(wpa_ie_buf);
Hai Shalomfdcde762020-04-02 11:19:20 -07003675 os_free(wpa_ie_buf2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003676}
3677
3678
3679SM_STATE(WPA_PTK, PTKINITDONE)
3680{
3681 SM_ENTRY_MA(WPA_PTK, PTKINITDONE, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07003682 sm->EAPOLKeyReceived = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003683 if (sm->Pair) {
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07003684 enum wpa_alg alg = wpa_cipher_to_alg(sm->pairwise);
3685 int klen = wpa_cipher_key_len(sm->pairwise);
Hai Shalomfdcde762020-04-02 11:19:20 -07003686 int res;
3687
3688 if (sm->use_ext_key_id)
3689 res = wpa_auth_set_key(sm->wpa_auth, 0, 0, sm->addr,
3690 sm->keyidx_active, NULL, 0,
3691 KEY_FLAG_PAIRWISE_RX_TX_MODIFY);
3692 else
3693 res = wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr,
3694 0, sm->PTK.tk, klen,
3695 KEY_FLAG_PAIRWISE_RX_TX);
3696 if (res) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003697 wpa_sta_disconnect(sm->wpa_auth, sm->addr,
3698 WLAN_REASON_PREV_AUTH_NOT_VALID);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003699 return;
3700 }
3701 /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */
Hai Shalome21d4e82020-04-29 16:34:06 -07003702 sm->pairwise_set = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003703
Hai Shalom81f62d82019-07-22 12:10:00 -07003704 wpa_auth_set_ptk_rekey_timer(sm);
Hai Shalom60840252021-02-19 19:02:11 -08003705 wpa_auth_store_ptksa(sm->wpa_auth, sm->addr, sm->pairwise,
3706 dot11RSNAConfigPMKLifetime, &sm->PTK);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003707
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003708 if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
3709 sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP ||
3710 sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003711 wpa_auth_set_eapol(sm->wpa_auth, sm->addr,
3712 WPA_EAPOL_authorized, 1);
3713 }
3714 }
3715
3716 if (0 /* IBSS == TRUE */) {
3717 sm->keycount++;
3718 if (sm->keycount == 2) {
3719 wpa_auth_set_eapol(sm->wpa_auth, sm->addr,
3720 WPA_EAPOL_portValid, 1);
3721 }
3722 } else {
3723 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid,
3724 1);
3725 }
Hai Shalome21d4e82020-04-29 16:34:06 -07003726 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyAvailable,
3727 false);
3728 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyDone, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003729 if (sm->wpa == WPA_VERSION_WPA)
Hai Shalome21d4e82020-04-29 16:34:06 -07003730 sm->PInitAKeys = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003731 else
Hai Shalome21d4e82020-04-29 16:34:06 -07003732 sm->has_GTK = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003733 wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO,
3734 "pairwise key handshake completed (%s)",
3735 sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN");
Hai Shaloma20dcd72022-02-04 13:43:00 -08003736 wpa_msg(sm->wpa_auth->conf.msg_ctx, MSG_INFO, "EAPOL-4WAY-HS-COMPLETED "
3737 MACSTR, MAC2STR(sm->addr));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003738
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003739#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003740 wpa_ft_push_pmk_r1(sm->wpa_auth, sm->addr);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003741#endif /* CONFIG_IEEE80211R_AP */
Sunil Ravia04bd252022-05-02 22:54:18 -07003742
3743 sm->ptkstart_without_success = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003744}
3745
3746
3747SM_STEP(WPA_PTK)
3748{
3749 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
Hai Shalomfdcde762020-04-02 11:19:20 -07003750 struct wpa_auth_config *conf = &wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003751
3752 if (sm->Init)
3753 SM_ENTER(WPA_PTK, INITIALIZE);
3754 else if (sm->Disconnect
3755 /* || FIX: dot11RSNAConfigSALifetime timeout */) {
3756 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
3757 "WPA_PTK: sm->Disconnect");
3758 SM_ENTER(WPA_PTK, DISCONNECT);
3759 }
3760 else if (sm->DeauthenticationRequest)
3761 SM_ENTER(WPA_PTK, DISCONNECTED);
3762 else if (sm->AuthenticationRequest)
3763 SM_ENTER(WPA_PTK, AUTHENTICATION);
3764 else if (sm->ReAuthenticationRequest)
3765 SM_ENTER(WPA_PTK, AUTHENTICATION2);
Jouni Malinen1420a892017-10-01 12:32:57 +03003766 else if (sm->PTKRequest) {
3767 if (wpa_auth_sm_ptk_update(sm) < 0)
3768 SM_ENTER(WPA_PTK, DISCONNECTED);
3769 else
3770 SM_ENTER(WPA_PTK, PTKSTART);
3771 } else switch (sm->wpa_ptk_state) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003772 case WPA_PTK_INITIALIZE:
3773 break;
3774 case WPA_PTK_DISCONNECT:
3775 SM_ENTER(WPA_PTK, DISCONNECTED);
3776 break;
3777 case WPA_PTK_DISCONNECTED:
3778 SM_ENTER(WPA_PTK, INITIALIZE);
3779 break;
3780 case WPA_PTK_AUTHENTICATION:
3781 SM_ENTER(WPA_PTK, AUTHENTICATION2);
3782 break;
3783 case WPA_PTK_AUTHENTICATION2:
3784 if (wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) &&
Hai Shalomfdcde762020-04-02 11:19:20 -07003785 wpa_auth_get_eapol(wpa_auth, sm->addr,
Hai Shalome21d4e82020-04-29 16:34:06 -07003786 WPA_EAPOL_keyRun))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003787 SM_ENTER(WPA_PTK, INITPMK);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003788 else if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
3789 sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003790 /* FIX: && 802.1X::keyRun */)
3791 SM_ENTER(WPA_PTK, INITPSK);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003792 else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP)
3793 SM_ENTER(WPA_PTK, INITPMK);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003794 break;
3795 case WPA_PTK_INITPMK:
Hai Shalomfdcde762020-04-02 11:19:20 -07003796 if (wpa_auth_get_eapol(wpa_auth, sm->addr,
Hai Shalome21d4e82020-04-29 16:34:06 -07003797 WPA_EAPOL_keyAvailable)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003798 SM_ENTER(WPA_PTK, PTKSTART);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003799#ifdef CONFIG_DPP
3800 } else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP && sm->pmksa) {
3801 SM_ENTER(WPA_PTK, PTKSTART);
3802#endif /* CONFIG_DPP */
3803 } else {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003804 wpa_auth->dot11RSNA4WayHandshakeFailures++;
Hai Shalomfdcde762020-04-02 11:19:20 -07003805 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003806 "INITPMK - keyAvailable = false");
3807 SM_ENTER(WPA_PTK, DISCONNECT);
3808 }
3809 break;
3810 case WPA_PTK_INITPSK:
Hai Shalomfdcde762020-04-02 11:19:20 -07003811 if (wpa_auth_get_psk(wpa_auth, sm->addr, sm->p2p_dev_addr,
Hai Shalom021b0b52019-04-10 11:17:58 -07003812 NULL, NULL, NULL)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003813 SM_ENTER(WPA_PTK, PTKSTART);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003814#ifdef CONFIG_SAE
3815 } else if (wpa_auth_uses_sae(sm) && sm->pmksa) {
3816 SM_ENTER(WPA_PTK, PTKSTART);
3817#endif /* CONFIG_SAE */
Sunil Ravia04bd252022-05-02 22:54:18 -07003818 } else if (wpa_key_mgmt_wpa_psk_no_sae(sm->wpa_key_mgmt) &&
3819 wpa_auth->conf.radius_psk) {
3820 wpa_printf(MSG_DEBUG,
3821 "INITPSK: No PSK yet available for STA - use RADIUS later");
3822 SM_ENTER(WPA_PTK, PTKSTART);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003823 } else {
Hai Shalomfdcde762020-04-02 11:19:20 -07003824 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003825 "no PSK configured for the STA");
3826 wpa_auth->dot11RSNA4WayHandshakeFailures++;
3827 SM_ENTER(WPA_PTK, DISCONNECT);
3828 }
3829 break;
3830 case WPA_PTK_PTKSTART:
3831 if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest &&
3832 sm->EAPOLKeyPairwise)
3833 SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING);
Hai Shalomfdcde762020-04-02 11:19:20 -07003834 else if (sm->TimeoutCtr > conf->wpa_pairwise_update_count) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003835 wpa_auth->dot11RSNA4WayHandshakeFailures++;
Hai Shalomfdcde762020-04-02 11:19:20 -07003836 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
3837 "PTKSTART: Retry limit %u reached",
3838 conf->wpa_pairwise_update_count);
Hai Shalome21d4e82020-04-29 16:34:06 -07003839 sm->disconnect_reason =
3840 WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003841 SM_ENTER(WPA_PTK, DISCONNECT);
3842 } else if (sm->TimeoutEvt)
3843 SM_ENTER(WPA_PTK, PTKSTART);
3844 break;
3845 case WPA_PTK_PTKCALCNEGOTIATING:
3846 if (sm->MICVerified)
3847 SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING2);
3848 else if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest &&
3849 sm->EAPOLKeyPairwise)
3850 SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING);
3851 else if (sm->TimeoutEvt)
3852 SM_ENTER(WPA_PTK, PTKSTART);
3853 break;
3854 case WPA_PTK_PTKCALCNEGOTIATING2:
3855 SM_ENTER(WPA_PTK, PTKINITNEGOTIATING);
3856 break;
3857 case WPA_PTK_PTKINITNEGOTIATING:
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003858 if (sm->update_snonce)
3859 SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING);
3860 else if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest &&
3861 sm->EAPOLKeyPairwise && sm->MICVerified)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003862 SM_ENTER(WPA_PTK, PTKINITDONE);
3863 else if (sm->TimeoutCtr >
Hai Shalomfdcde762020-04-02 11:19:20 -07003864 conf->wpa_pairwise_update_count ||
3865 (conf->wpa_disable_eapol_key_retries &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003866 sm->TimeoutCtr > 1)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003867 wpa_auth->dot11RSNA4WayHandshakeFailures++;
Hai Shalomfdcde762020-04-02 11:19:20 -07003868 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
3869 "PTKINITNEGOTIATING: Retry limit %u reached",
3870 conf->wpa_pairwise_update_count);
Hai Shalome21d4e82020-04-29 16:34:06 -07003871 sm->disconnect_reason =
3872 WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003873 SM_ENTER(WPA_PTK, DISCONNECT);
3874 } else if (sm->TimeoutEvt)
3875 SM_ENTER(WPA_PTK, PTKINITNEGOTIATING);
3876 break;
3877 case WPA_PTK_PTKINITDONE:
3878 break;
3879 }
3880}
3881
3882
3883SM_STATE(WPA_PTK_GROUP, IDLE)
3884{
3885 SM_ENTRY_MA(WPA_PTK_GROUP, IDLE, wpa_ptk_group);
3886 if (sm->Init) {
3887 /* Init flag is not cleared here, so avoid busy
3888 * loop by claiming nothing changed. */
Hai Shalome21d4e82020-04-29 16:34:06 -07003889 sm->changed = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003890 }
3891 sm->GTimeoutCtr = 0;
3892}
3893
3894
3895SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING)
3896{
3897 u8 rsc[WPA_KEY_RSC_LEN];
3898 struct wpa_group *gsm = sm->group;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003899 const u8 *kde;
3900 u8 *kde_buf = NULL, *pos, hdr[2];
Sunil Ravia04bd252022-05-02 22:54:18 -07003901 size_t kde_len = 0;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003902 u8 *gtk, stub_gtk[32];
Hai Shalomfdcde762020-04-02 11:19:20 -07003903 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003904
3905 SM_ENTRY_MA(WPA_PTK_GROUP, REKEYNEGOTIATING, wpa_ptk_group);
3906
3907 sm->GTimeoutCtr++;
Hai Shalomfdcde762020-04-02 11:19:20 -07003908 if (conf->wpa_disable_eapol_key_retries && sm->GTimeoutCtr > 1) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003909 /* Do not allow retransmission of EAPOL-Key group msg 1/2 */
3910 return;
3911 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003912 if (sm->GTimeoutCtr > conf->wpa_group_update_count) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003913 /* No point in sending the EAPOL-Key - we will disconnect
3914 * immediately following this. */
3915 return;
3916 }
3917
3918 if (sm->wpa == WPA_VERSION_WPA)
Hai Shalome21d4e82020-04-29 16:34:06 -07003919 sm->PInitAKeys = false;
3920 sm->TimeoutEvt = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003921 /* Send EAPOL(1, 1, 1, !Pair, G, RSC, GNonce, MIC(PTK), GTK[GN]) */
3922 os_memset(rsc, 0, WPA_KEY_RSC_LEN);
3923 if (gsm->wpa_group_state == WPA_GROUP_SETKEYSDONE)
3924 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc);
3925 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
3926 "sending 1/2 msg of Group Key Handshake");
3927
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003928 gtk = gsm->GTK[gsm->GN - 1];
Hai Shalomfdcde762020-04-02 11:19:20 -07003929 if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003930 /*
3931 * Provide unique random GTK to each STA to prevent use
3932 * of GTK in the BSS.
3933 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003934 if (random_get_bytes(stub_gtk, gsm->GTK_len) < 0)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003935 return;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003936 gtk = stub_gtk;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003937 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003938 if (sm->wpa == WPA_VERSION_WPA2) {
3939 kde_len = 2 + RSN_SELECTOR_LEN + 2 + gsm->GTK_len +
Hai Shalom74f70d42019-02-11 14:42:39 -08003940 ieee80211w_kde_len(sm) + ocv_oci_len(sm);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003941 kde_buf = os_malloc(kde_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07003942 if (!kde_buf)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003943 return;
3944
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003945 kde = pos = kde_buf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003946 hdr[0] = gsm->GN & 0x03;
3947 hdr[1] = 0;
3948 pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003949 gtk, gsm->GTK_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003950 pos = ieee80211w_kde_add(sm, pos);
Hai Shalom899fcc72020-10-19 14:38:18 -07003951 if (ocv_oci_add(sm, &pos,
3952 conf->oci_freq_override_eapol_g1) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -08003953 os_free(kde_buf);
3954 return;
3955 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003956 kde_len = pos - kde;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003957 } else {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003958 kde = gtk;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003959 kde_len = gsm->GTK_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003960 }
3961
3962 wpa_send_eapol(sm->wpa_auth, sm,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003963 WPA_KEY_INFO_SECURE |
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003964 (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
3965 WPA_KEY_INFO_MIC : 0) |
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003966 WPA_KEY_INFO_ACK |
3967 (!sm->Pair ? WPA_KEY_INFO_INSTALL : 0),
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003968 rsc, NULL, kde, kde_len, gsm->GN, 1);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003969
Sunil Ravia04bd252022-05-02 22:54:18 -07003970 bin_clear_free(kde_buf, kde_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003971}
3972
3973
3974SM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED)
3975{
Hai Shalom74f70d42019-02-11 14:42:39 -08003976 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
Hai Shalomfdcde762020-04-02 11:19:20 -07003977#ifdef CONFIG_OCV
Hai Shalom74f70d42019-02-11 14:42:39 -08003978 const u8 *key_data, *mic;
3979 struct ieee802_1x_hdr *hdr;
3980 struct wpa_eapol_key *key;
3981 struct wpa_eapol_ie_parse kde;
3982 size_t mic_len;
3983 u16 key_data_length;
3984#endif /* CONFIG_OCV */
3985
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003986 SM_ENTRY_MA(WPA_PTK_GROUP, REKEYESTABLISHED, wpa_ptk_group);
Hai Shalome21d4e82020-04-29 16:34:06 -07003987 sm->EAPOLKeyReceived = false;
Hai Shalom74f70d42019-02-11 14:42:39 -08003988
3989#ifdef CONFIG_OCV
3990 mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
3991
3992 /*
3993 * Note: last_rx_eapol_key length fields have already been validated in
3994 * wpa_receive().
3995 */
3996 hdr = (struct ieee802_1x_hdr *) sm->last_rx_eapol_key;
3997 key = (struct wpa_eapol_key *) (hdr + 1);
3998 mic = (u8 *) (key + 1);
3999 key_data = mic + mic_len + 2;
4000 key_data_length = WPA_GET_BE16(mic + mic_len);
4001 if (key_data_length > sm->last_rx_eapol_key_len - sizeof(*hdr) -
4002 sizeof(*key) - mic_len - 2)
4003 return;
4004
4005 if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) {
4006 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
4007 "received EAPOL-Key group msg 2/2 with invalid Key Data contents");
4008 return;
4009 }
4010
4011 if (wpa_auth_uses_ocv(sm)) {
4012 struct wpa_channel_info ci;
4013 int tx_chanwidth;
4014 int tx_seg1_idx;
4015
4016 if (wpa_channel_info(wpa_auth, &ci) != 0) {
4017 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalom899fcc72020-10-19 14:38:18 -07004018 "Failed to get channel info to validate received OCI in EAPOL-Key group 2/2");
Hai Shalom74f70d42019-02-11 14:42:39 -08004019 return;
4020 }
4021
4022 if (get_sta_tx_parameters(sm,
4023 channel_width_to_int(ci.chanwidth),
4024 ci.seg1_idx, &tx_chanwidth,
4025 &tx_seg1_idx) < 0)
4026 return;
4027
4028 if (ocv_verify_tx_params(kde.oci, kde.oci_len, &ci,
Hai Shalom899fcc72020-10-19 14:38:18 -07004029 tx_chanwidth, tx_seg1_idx) !=
4030 OCI_SUCCESS) {
4031 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
4032 "OCV failed: %s", ocv_errorstr);
4033 if (wpa_auth->conf.msg_ctx)
4034 wpa_msg(wpa_auth->conf.msg_ctx, MSG_INFO,
4035 OCV_FAILURE "addr=" MACSTR
4036 " frame=eapol-key-g2 error=%s",
4037 MAC2STR(sm->addr), ocv_errorstr);
Hai Shalom74f70d42019-02-11 14:42:39 -08004038 return;
4039 }
4040 }
4041#endif /* CONFIG_OCV */
4042
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004043 if (sm->GUpdateStationKeys)
4044 sm->group->GKeyDoneStations--;
Hai Shalome21d4e82020-04-29 16:34:06 -07004045 sm->GUpdateStationKeys = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004046 sm->GTimeoutCtr = 0;
4047 /* FIX: MLME.SetProtection.Request(TA, Tx_Rx) */
Hai Shalomfdcde762020-04-02 11:19:20 -07004048 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004049 "group key handshake completed (%s)",
4050 sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN");
Hai Shalome21d4e82020-04-29 16:34:06 -07004051 sm->has_GTK = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004052}
4053
4054
4055SM_STATE(WPA_PTK_GROUP, KEYERROR)
4056{
4057 SM_ENTRY_MA(WPA_PTK_GROUP, KEYERROR, wpa_ptk_group);
4058 if (sm->GUpdateStationKeys)
4059 sm->group->GKeyDoneStations--;
Hai Shalome21d4e82020-04-29 16:34:06 -07004060 sm->GUpdateStationKeys = false;
4061 sm->Disconnect = true;
4062 sm->disconnect_reason = WLAN_REASON_GROUP_KEY_UPDATE_TIMEOUT;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004063 wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO,
4064 "group key handshake failed (%s) after %u tries",
4065 sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN",
4066 sm->wpa_auth->conf.wpa_group_update_count);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004067}
4068
4069
4070SM_STEP(WPA_PTK_GROUP)
4071{
4072 if (sm->Init || sm->PtkGroupInit) {
4073 SM_ENTER(WPA_PTK_GROUP, IDLE);
Hai Shalome21d4e82020-04-29 16:34:06 -07004074 sm->PtkGroupInit = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004075 } else switch (sm->wpa_ptk_group_state) {
4076 case WPA_PTK_GROUP_IDLE:
4077 if (sm->GUpdateStationKeys ||
4078 (sm->wpa == WPA_VERSION_WPA && sm->PInitAKeys))
4079 SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING);
4080 break;
4081 case WPA_PTK_GROUP_REKEYNEGOTIATING:
4082 if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest &&
4083 !sm->EAPOLKeyPairwise && sm->MICVerified)
4084 SM_ENTER(WPA_PTK_GROUP, REKEYESTABLISHED);
4085 else if (sm->GTimeoutCtr >
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004086 sm->wpa_auth->conf.wpa_group_update_count ||
4087 (sm->wpa_auth->conf.wpa_disable_eapol_key_retries &&
4088 sm->GTimeoutCtr > 1))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004089 SM_ENTER(WPA_PTK_GROUP, KEYERROR);
4090 else if (sm->TimeoutEvt)
4091 SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING);
4092 break;
4093 case WPA_PTK_GROUP_KEYERROR:
4094 SM_ENTER(WPA_PTK_GROUP, IDLE);
4095 break;
4096 case WPA_PTK_GROUP_REKEYESTABLISHED:
4097 SM_ENTER(WPA_PTK_GROUP, IDLE);
4098 break;
4099 }
4100}
4101
4102
4103static int wpa_gtk_update(struct wpa_authenticator *wpa_auth,
4104 struct wpa_group *group)
4105{
Hai Shalomfdcde762020-04-02 11:19:20 -07004106 struct wpa_auth_config *conf = &wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004107 int ret = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07004108 size_t len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004109
4110 os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
4111 inc_byte_array(group->Counter, WPA_NONCE_LEN);
4112 if (wpa_gmk_to_gtk(group->GMK, "Group key expansion",
4113 wpa_auth->addr, group->GNonce,
4114 group->GTK[group->GN - 1], group->GTK_len) < 0)
4115 ret = -1;
4116 wpa_hexdump_key(MSG_DEBUG, "GTK",
4117 group->GTK[group->GN - 1], group->GTK_len);
4118
Hai Shalomfdcde762020-04-02 11:19:20 -07004119 if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
4120 len = wpa_cipher_key_len(conf->group_mgmt_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004121 os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
4122 inc_byte_array(group->Counter, WPA_NONCE_LEN);
4123 if (wpa_gmk_to_gtk(group->GMK, "IGTK key expansion",
4124 wpa_auth->addr, group->GNonce,
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004125 group->IGTK[group->GN_igtk - 4], len) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004126 ret = -1;
4127 wpa_hexdump_key(MSG_DEBUG, "IGTK",
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004128 group->IGTK[group->GN_igtk - 4], len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004129 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004130
Hai Shalomfdcde762020-04-02 11:19:20 -07004131 if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION &&
4132 conf->beacon_prot) {
4133 len = wpa_cipher_key_len(conf->group_mgmt_cipher);
4134 os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
4135 inc_byte_array(group->Counter, WPA_NONCE_LEN);
4136 if (wpa_gmk_to_gtk(group->GMK, "BIGTK key expansion",
4137 wpa_auth->addr, group->GNonce,
4138 group->BIGTK[group->GN_bigtk - 6], len) < 0)
4139 ret = -1;
4140 wpa_hexdump_key(MSG_DEBUG, "BIGTK",
4141 group->BIGTK[group->GN_bigtk - 6], len);
4142 }
4143
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004144 return ret;
4145}
4146
4147
4148static void wpa_group_gtk_init(struct wpa_authenticator *wpa_auth,
4149 struct wpa_group *group)
4150{
Hai Shalomfdcde762020-04-02 11:19:20 -07004151 wpa_printf(MSG_DEBUG,
4152 "WPA: group state machine entering state GTK_INIT (VLAN-ID %d)",
4153 group->vlan_id);
Hai Shalome21d4e82020-04-29 16:34:06 -07004154 group->changed = false; /* GInit is not cleared here; avoid loop */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004155 group->wpa_group_state = WPA_GROUP_GTK_INIT;
4156
4157 /* GTK[0..N] = 0 */
4158 os_memset(group->GTK, 0, sizeof(group->GTK));
4159 group->GN = 1;
4160 group->GM = 2;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004161 group->GN_igtk = 4;
4162 group->GM_igtk = 5;
Hai Shalomfdcde762020-04-02 11:19:20 -07004163 group->GN_bigtk = 6;
4164 group->GM_bigtk = 7;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004165 /* GTK[GN] = CalcGTK() */
4166 wpa_gtk_update(wpa_auth, group);
4167}
4168
4169
4170static int wpa_group_update_sta(struct wpa_state_machine *sm, void *ctx)
4171{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004172 if (ctx != NULL && ctx != sm->group)
4173 return 0;
4174
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004175 if (sm->wpa_ptk_state != WPA_PTK_PTKINITDONE) {
4176 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
4177 "Not in PTKINITDONE; skip Group Key update");
Hai Shalome21d4e82020-04-29 16:34:06 -07004178 sm->GUpdateStationKeys = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004179 return 0;
4180 }
4181 if (sm->GUpdateStationKeys) {
4182 /*
4183 * This should not really happen, so add a debug log entry.
4184 * Since we clear the GKeyDoneStations before the loop, the
4185 * station needs to be counted here anyway.
4186 */
4187 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07004188 "GUpdateStationKeys was already set when marking station for GTK rekeying");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004189 }
4190
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004191 /* Do not rekey GTK/IGTK when STA is in WNM-Sleep Mode */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004192 if (sm->is_wnmsleep)
4193 return 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004194
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004195 sm->group->GKeyDoneStations++;
Hai Shalome21d4e82020-04-29 16:34:06 -07004196 sm->GUpdateStationKeys = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004197
4198 wpa_sm_step(sm);
4199 return 0;
4200}
4201
4202
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004203#ifdef CONFIG_WNM_AP
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004204/* update GTK when exiting WNM-Sleep Mode */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004205void wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm)
4206{
Hai Shalomfdcde762020-04-02 11:19:20 -07004207 if (!sm || sm->is_wnmsleep)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004208 return;
4209
4210 wpa_group_update_sta(sm, NULL);
4211}
4212
4213
4214void wpa_set_wnmsleep(struct wpa_state_machine *sm, int flag)
4215{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004216 if (sm)
4217 sm->is_wnmsleep = !!flag;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004218}
4219
4220
4221int wpa_wnmsleep_gtk_subelem(struct wpa_state_machine *sm, u8 *pos)
4222{
Hai Shalom899fcc72020-10-19 14:38:18 -07004223 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004224 struct wpa_group *gsm = sm->group;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004225 u8 *start = pos;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004226
4227 /*
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004228 * GTK subelement:
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004229 * Sub-elem ID[1] | Length[1] | Key Info[2] | Key Length[1] | RSC[8] |
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004230 * Key[5..32]
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004231 */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004232 *pos++ = WNM_SLEEP_SUBELEM_GTK;
4233 *pos++ = 11 + gsm->GTK_len;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004234 /* Key ID in B0-B1 of Key Info */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004235 WPA_PUT_LE16(pos, gsm->GN & 0x03);
4236 pos += 2;
4237 *pos++ = gsm->GTK_len;
4238 if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, pos) != 0)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004239 return 0;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004240 pos += 8;
4241 os_memcpy(pos, gsm->GTK[gsm->GN - 1], gsm->GTK_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07004242 if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
4243 /*
4244 * Provide unique random GTK to each STA to prevent use
4245 * of GTK in the BSS.
4246 */
4247 if (random_get_bytes(pos, gsm->GTK_len) < 0)
4248 return 0;
4249 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004250 pos += gsm->GTK_len;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004251
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004252 wpa_printf(MSG_DEBUG, "WNM: GTK Key ID %u in WNM-Sleep Mode exit",
4253 gsm->GN);
4254 wpa_hexdump_key(MSG_DEBUG, "WNM: GTK in WNM-Sleep Mode exit",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004255 gsm->GTK[gsm->GN - 1], gsm->GTK_len);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004256
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004257 return pos - start;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004258}
4259
4260
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004261int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos)
4262{
Hai Shalom899fcc72020-10-19 14:38:18 -07004263 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004264 struct wpa_group *gsm = sm->group;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004265 u8 *start = pos;
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004266 size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004267
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004268 /*
4269 * IGTK subelement:
4270 * Sub-elem ID[1] | Length[1] | KeyID[2] | PN[6] | Key[16]
4271 */
4272 *pos++ = WNM_SLEEP_SUBELEM_IGTK;
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004273 *pos++ = 2 + 6 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004274 WPA_PUT_LE16(pos, gsm->GN_igtk);
4275 pos += 2;
4276 if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, pos) != 0)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004277 return 0;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004278 pos += 6;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004279
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004280 os_memcpy(pos, gsm->IGTK[gsm->GN_igtk - 4], len);
Hai Shalom899fcc72020-10-19 14:38:18 -07004281 if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
4282 /*
4283 * Provide unique random IGTK to each STA to prevent use
4284 * of IGTK in the BSS.
4285 */
4286 if (random_get_bytes(pos, len) < 0)
4287 return 0;
4288 }
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004289 pos += len;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004290
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004291 wpa_printf(MSG_DEBUG, "WNM: IGTK Key ID %u in WNM-Sleep Mode exit",
4292 gsm->GN_igtk);
4293 wpa_hexdump_key(MSG_DEBUG, "WNM: IGTK in WNM-Sleep Mode exit",
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004294 gsm->IGTK[gsm->GN_igtk - 4], len);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004295
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004296 return pos - start;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004297}
Hai Shalomc3565922019-10-28 11:58:20 -07004298
Hai Shalomfdcde762020-04-02 11:19:20 -07004299
4300int wpa_wnmsleep_bigtk_subelem(struct wpa_state_machine *sm, u8 *pos)
4301{
4302 struct wpa_group *gsm = sm->group;
4303 u8 *start = pos;
4304 size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
4305
4306 /*
4307 * BIGTK subelement:
4308 * Sub-elem ID[1] | Length[1] | KeyID[2] | PN[6] | Key[16]
4309 */
4310 *pos++ = WNM_SLEEP_SUBELEM_BIGTK;
4311 *pos++ = 2 + 6 + len;
4312 WPA_PUT_LE16(pos, gsm->GN_bigtk);
4313 pos += 2;
4314 if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_bigtk, pos) != 0)
4315 return 0;
4316 pos += 6;
4317
4318 os_memcpy(pos, gsm->BIGTK[gsm->GN_bigtk - 6], len);
Hai Shalom899fcc72020-10-19 14:38:18 -07004319 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
4320 /*
4321 * Provide unique random BIGTK to each STA to prevent use
4322 * of BIGTK in the BSS.
4323 */
4324 if (random_get_bytes(pos, len) < 0)
4325 return 0;
4326 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004327 pos += len;
4328
4329 wpa_printf(MSG_DEBUG, "WNM: BIGTK Key ID %u in WNM-Sleep Mode exit",
4330 gsm->GN_bigtk);
4331 wpa_hexdump_key(MSG_DEBUG, "WNM: BIGTK in WNM-Sleep Mode exit",
Hai Shaloma20dcd72022-02-04 13:43:00 -08004332 gsm->BIGTK[gsm->GN_bigtk - 6], len);
Hai Shalomfdcde762020-04-02 11:19:20 -07004333
4334 return pos - start;
4335}
4336
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004337#endif /* CONFIG_WNM_AP */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004338
4339
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004340static void wpa_group_setkeys(struct wpa_authenticator *wpa_auth,
4341 struct wpa_group *group)
4342{
4343 int tmp;
4344
Hai Shalomfdcde762020-04-02 11:19:20 -07004345 wpa_printf(MSG_DEBUG,
4346 "WPA: group state machine entering state SETKEYS (VLAN-ID %d)",
4347 group->vlan_id);
Hai Shalome21d4e82020-04-29 16:34:06 -07004348 group->changed = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004349 group->wpa_group_state = WPA_GROUP_SETKEYS;
Hai Shalome21d4e82020-04-29 16:34:06 -07004350 group->GTKReKey = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004351 tmp = group->GM;
4352 group->GM = group->GN;
4353 group->GN = tmp;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004354 tmp = group->GM_igtk;
4355 group->GM_igtk = group->GN_igtk;
4356 group->GN_igtk = tmp;
Hai Shalomfdcde762020-04-02 11:19:20 -07004357 tmp = group->GM_bigtk;
4358 group->GM_bigtk = group->GN_bigtk;
4359 group->GN_bigtk = tmp;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004360 /* "GKeyDoneStations = GNoStations" is done in more robust way by
4361 * counting the STAs that are marked with GUpdateStationKeys instead of
4362 * including all STAs that could be in not-yet-completed state. */
4363 wpa_gtk_update(wpa_auth, group);
4364
4365 if (group->GKeyDoneStations) {
Hai Shalomfdcde762020-04-02 11:19:20 -07004366 wpa_printf(MSG_DEBUG,
4367 "wpa_group_setkeys: Unexpected GKeyDoneStations=%d when starting new GTK rekey",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004368 group->GKeyDoneStations);
4369 group->GKeyDoneStations = 0;
4370 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004371 wpa_auth_for_each_sta(wpa_auth, wpa_group_update_sta, group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004372 wpa_printf(MSG_DEBUG, "wpa_group_setkeys: GKeyDoneStations=%d",
4373 group->GKeyDoneStations);
4374}
4375
4376
4377static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth,
4378 struct wpa_group *group)
4379{
Hai Shalomfdcde762020-04-02 11:19:20 -07004380 struct wpa_auth_config *conf = &wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004381 int ret = 0;
4382
4383 if (wpa_auth_set_key(wpa_auth, group->vlan_id,
Hai Shalomfdcde762020-04-02 11:19:20 -07004384 wpa_cipher_to_alg(conf->wpa_group),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004385 broadcast_ether_addr, group->GN,
Hai Shalomfdcde762020-04-02 11:19:20 -07004386 group->GTK[group->GN - 1], group->GTK_len,
4387 KEY_FLAG_GROUP_TX_DEFAULT) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004388 ret = -1;
4389
Hai Shalomfdcde762020-04-02 11:19:20 -07004390 if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004391 enum wpa_alg alg;
4392 size_t len;
4393
Hai Shalomfdcde762020-04-02 11:19:20 -07004394 alg = wpa_cipher_to_alg(conf->group_mgmt_cipher);
4395 len = wpa_cipher_key_len(conf->group_mgmt_cipher);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004396
4397 if (ret == 0 &&
4398 wpa_auth_set_key(wpa_auth, group->vlan_id, alg,
4399 broadcast_ether_addr, group->GN_igtk,
Hai Shalomfdcde762020-04-02 11:19:20 -07004400 group->IGTK[group->GN_igtk - 4], len,
4401 KEY_FLAG_GROUP_TX_DEFAULT) < 0)
4402 ret = -1;
4403
4404 if (ret == 0 && conf->beacon_prot &&
4405 wpa_auth_set_key(wpa_auth, group->vlan_id, alg,
4406 broadcast_ether_addr, group->GN_bigtk,
4407 group->BIGTK[group->GN_bigtk - 6], len,
4408 KEY_FLAG_GROUP_TX_DEFAULT) < 0)
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004409 ret = -1;
4410 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004411
4412 return ret;
4413}
4414
4415
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004416static int wpa_group_disconnect_cb(struct wpa_state_machine *sm, void *ctx)
4417{
4418 if (sm->group == ctx) {
4419 wpa_printf(MSG_DEBUG, "WPA: Mark STA " MACSTR
Hai Shalomfdcde762020-04-02 11:19:20 -07004420 " for disconnection due to fatal failure",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004421 MAC2STR(sm->addr));
Hai Shalome21d4e82020-04-29 16:34:06 -07004422 sm->Disconnect = true;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004423 }
4424
4425 return 0;
4426}
4427
4428
4429static void wpa_group_fatal_failure(struct wpa_authenticator *wpa_auth,
4430 struct wpa_group *group)
4431{
Hai Shalomfdcde762020-04-02 11:19:20 -07004432 wpa_printf(MSG_DEBUG,
4433 "WPA: group state machine entering state FATAL_FAILURE");
Hai Shalome21d4e82020-04-29 16:34:06 -07004434 group->changed = true;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004435 group->wpa_group_state = WPA_GROUP_FATAL_FAILURE;
4436 wpa_auth_for_each_sta(wpa_auth, wpa_group_disconnect_cb, group);
4437}
4438
4439
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004440static int wpa_group_setkeysdone(struct wpa_authenticator *wpa_auth,
4441 struct wpa_group *group)
4442{
Hai Shalomfdcde762020-04-02 11:19:20 -07004443 wpa_printf(MSG_DEBUG,
4444 "WPA: group state machine entering state SETKEYSDONE (VLAN-ID %d)",
4445 group->vlan_id);
Hai Shalome21d4e82020-04-29 16:34:06 -07004446 group->changed = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004447 group->wpa_group_state = WPA_GROUP_SETKEYSDONE;
4448
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004449 if (wpa_group_config_group_keys(wpa_auth, group) < 0) {
4450 wpa_group_fatal_failure(wpa_auth, group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004451 return -1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004452 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004453
4454 return 0;
4455}
4456
4457
4458static void wpa_group_sm_step(struct wpa_authenticator *wpa_auth,
4459 struct wpa_group *group)
4460{
4461 if (group->GInit) {
4462 wpa_group_gtk_init(wpa_auth, group);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004463 } else if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) {
4464 /* Do not allow group operations */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004465 } else if (group->wpa_group_state == WPA_GROUP_GTK_INIT &&
4466 group->GTKAuthenticator) {
4467 wpa_group_setkeysdone(wpa_auth, group);
4468 } else if (group->wpa_group_state == WPA_GROUP_SETKEYSDONE &&
4469 group->GTKReKey) {
4470 wpa_group_setkeys(wpa_auth, group);
4471 } else if (group->wpa_group_state == WPA_GROUP_SETKEYS) {
4472 if (group->GKeyDoneStations == 0)
4473 wpa_group_setkeysdone(wpa_auth, group);
4474 else if (group->GTKReKey)
4475 wpa_group_setkeys(wpa_auth, group);
4476 }
4477}
4478
4479
4480static int wpa_sm_step(struct wpa_state_machine *sm)
4481{
Hai Shalomfdcde762020-04-02 11:19:20 -07004482 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004483 return 0;
4484
4485 if (sm->in_step_loop) {
4486 /* This should not happen, but if it does, make sure we do not
4487 * end up freeing the state machine too early by exiting the
4488 * recursive call. */
4489 wpa_printf(MSG_ERROR, "WPA: wpa_sm_step() called recursively");
4490 return 0;
4491 }
4492
4493 sm->in_step_loop = 1;
4494 do {
4495 if (sm->pending_deinit)
4496 break;
4497
Hai Shalome21d4e82020-04-29 16:34:06 -07004498 sm->changed = false;
4499 sm->wpa_auth->group->changed = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004500
4501 SM_STEP_RUN(WPA_PTK);
4502 if (sm->pending_deinit)
4503 break;
4504 SM_STEP_RUN(WPA_PTK_GROUP);
4505 if (sm->pending_deinit)
4506 break;
4507 wpa_group_sm_step(sm->wpa_auth, sm->group);
4508 } while (sm->changed || sm->wpa_auth->group->changed);
4509 sm->in_step_loop = 0;
4510
4511 if (sm->pending_deinit) {
Hai Shalomfdcde762020-04-02 11:19:20 -07004512 wpa_printf(MSG_DEBUG,
4513 "WPA: Completing pending STA state machine deinit for "
4514 MACSTR, MAC2STR(sm->addr));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004515 wpa_free_sta_sm(sm);
4516 return 1;
4517 }
4518 return 0;
4519}
4520
4521
4522static void wpa_sm_call_step(void *eloop_ctx, void *timeout_ctx)
4523{
4524 struct wpa_state_machine *sm = eloop_ctx;
4525 wpa_sm_step(sm);
4526}
4527
4528
4529void wpa_auth_sm_notify(struct wpa_state_machine *sm)
4530{
Hai Shalomfdcde762020-04-02 11:19:20 -07004531 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004532 return;
4533 eloop_register_timeout(0, 0, wpa_sm_call_step, sm, NULL);
4534}
4535
4536
4537void wpa_gtk_rekey(struct wpa_authenticator *wpa_auth)
4538{
4539 int tmp, i;
4540 struct wpa_group *group;
4541
Hai Shalomfdcde762020-04-02 11:19:20 -07004542 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004543 return;
4544
4545 group = wpa_auth->group;
4546
4547 for (i = 0; i < 2; i++) {
4548 tmp = group->GM;
4549 group->GM = group->GN;
4550 group->GN = tmp;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004551 tmp = group->GM_igtk;
4552 group->GM_igtk = group->GN_igtk;
4553 group->GN_igtk = tmp;
Hai Shalomfdcde762020-04-02 11:19:20 -07004554 tmp = group->GM_bigtk;
4555 group->GM_bigtk = group->GN_bigtk;
4556 group->GN_bigtk = tmp;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004557 wpa_gtk_update(wpa_auth, group);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004558 wpa_group_config_group_keys(wpa_auth, group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004559 }
4560}
4561
4562
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004563static const char * wpa_bool_txt(int val)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004564{
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004565 return val ? "TRUE" : "FALSE";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004566}
4567
4568
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004569#define RSN_SUITE "%02x-%02x-%02x-%d"
4570#define RSN_SUITE_ARG(s) \
4571((s) >> 24) & 0xff, ((s) >> 16) & 0xff, ((s) >> 8) & 0xff, (s) & 0xff
4572
4573int wpa_get_mib(struct wpa_authenticator *wpa_auth, char *buf, size_t buflen)
4574{
Hai Shalomfdcde762020-04-02 11:19:20 -07004575 struct wpa_auth_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004576 int len = 0, ret;
4577 char pmkid_txt[PMKID_LEN * 2 + 1];
4578#ifdef CONFIG_RSN_PREAUTH
4579 const int preauth = 1;
4580#else /* CONFIG_RSN_PREAUTH */
4581 const int preauth = 0;
4582#endif /* CONFIG_RSN_PREAUTH */
4583
Hai Shalomfdcde762020-04-02 11:19:20 -07004584 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004585 return len;
Hai Shalomfdcde762020-04-02 11:19:20 -07004586 conf = &wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004587
4588 ret = os_snprintf(buf + len, buflen - len,
4589 "dot11RSNAOptionImplemented=TRUE\n"
4590 "dot11RSNAPreauthenticationImplemented=%s\n"
4591 "dot11RSNAEnabled=%s\n"
4592 "dot11RSNAPreauthenticationEnabled=%s\n",
4593 wpa_bool_txt(preauth),
Hai Shalomfdcde762020-04-02 11:19:20 -07004594 wpa_bool_txt(conf->wpa & WPA_PROTO_RSN),
4595 wpa_bool_txt(conf->rsn_preauth));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004596 if (os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004597 return len;
4598 len += ret;
4599
4600 wpa_snprintf_hex(pmkid_txt, sizeof(pmkid_txt),
4601 wpa_auth->dot11RSNAPMKIDUsed, PMKID_LEN);
4602
4603 ret = os_snprintf(
4604 buf + len, buflen - len,
4605 "dot11RSNAConfigVersion=%u\n"
4606 "dot11RSNAConfigPairwiseKeysSupported=9999\n"
4607 /* FIX: dot11RSNAConfigGroupCipher */
4608 /* FIX: dot11RSNAConfigGroupRekeyMethod */
4609 /* FIX: dot11RSNAConfigGroupRekeyTime */
4610 /* FIX: dot11RSNAConfigGroupRekeyPackets */
4611 "dot11RSNAConfigGroupRekeyStrict=%u\n"
4612 "dot11RSNAConfigGroupUpdateCount=%u\n"
4613 "dot11RSNAConfigPairwiseUpdateCount=%u\n"
4614 "dot11RSNAConfigGroupCipherSize=%u\n"
4615 "dot11RSNAConfigPMKLifetime=%u\n"
4616 "dot11RSNAConfigPMKReauthThreshold=%u\n"
4617 "dot11RSNAConfigNumberOfPTKSAReplayCounters=0\n"
4618 "dot11RSNAConfigSATimeout=%u\n"
4619 "dot11RSNAAuthenticationSuiteSelected=" RSN_SUITE "\n"
4620 "dot11RSNAPairwiseCipherSelected=" RSN_SUITE "\n"
4621 "dot11RSNAGroupCipherSelected=" RSN_SUITE "\n"
4622 "dot11RSNAPMKIDUsed=%s\n"
4623 "dot11RSNAAuthenticationSuiteRequested=" RSN_SUITE "\n"
4624 "dot11RSNAPairwiseCipherRequested=" RSN_SUITE "\n"
4625 "dot11RSNAGroupCipherRequested=" RSN_SUITE "\n"
4626 "dot11RSNATKIPCounterMeasuresInvoked=%u\n"
4627 "dot11RSNA4WayHandshakeFailures=%u\n"
4628 "dot11RSNAConfigNumberOfGTKSAReplayCounters=0\n",
4629 RSN_VERSION,
Hai Shalomfdcde762020-04-02 11:19:20 -07004630 !!conf->wpa_strict_rekey,
4631 conf->wpa_group_update_count,
4632 conf->wpa_pairwise_update_count,
4633 wpa_cipher_key_len(conf->wpa_group) * 8,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004634 dot11RSNAConfigPMKLifetime,
4635 dot11RSNAConfigPMKReauthThreshold,
4636 dot11RSNAConfigSATimeout,
4637 RSN_SUITE_ARG(wpa_auth->dot11RSNAAuthenticationSuiteSelected),
4638 RSN_SUITE_ARG(wpa_auth->dot11RSNAPairwiseCipherSelected),
4639 RSN_SUITE_ARG(wpa_auth->dot11RSNAGroupCipherSelected),
4640 pmkid_txt,
4641 RSN_SUITE_ARG(wpa_auth->dot11RSNAAuthenticationSuiteRequested),
4642 RSN_SUITE_ARG(wpa_auth->dot11RSNAPairwiseCipherRequested),
4643 RSN_SUITE_ARG(wpa_auth->dot11RSNAGroupCipherRequested),
4644 wpa_auth->dot11RSNATKIPCounterMeasuresInvoked,
4645 wpa_auth->dot11RSNA4WayHandshakeFailures);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004646 if (os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004647 return len;
4648 len += ret;
4649
4650 /* TODO: dot11RSNAConfigPairwiseCiphersTable */
4651 /* TODO: dot11RSNAConfigAuthenticationSuitesTable */
4652
4653 /* Private MIB */
4654 ret = os_snprintf(buf + len, buflen - len, "hostapdWPAGroupState=%d\n",
4655 wpa_auth->group->wpa_group_state);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004656 if (os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004657 return len;
4658 len += ret;
4659
4660 return len;
4661}
4662
4663
4664int wpa_get_mib_sta(struct wpa_state_machine *sm, char *buf, size_t buflen)
4665{
4666 int len = 0, ret;
4667 u32 pairwise = 0;
4668
Hai Shalomfdcde762020-04-02 11:19:20 -07004669 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004670 return 0;
4671
4672 /* TODO: FF-FF-FF-FF-FF-FF entry for broadcast/multicast stats */
4673
4674 /* dot11RSNAStatsEntry */
4675
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07004676 pairwise = wpa_cipher_to_suite(sm->wpa == WPA_VERSION_WPA2 ?
4677 WPA_PROTO_RSN : WPA_PROTO_WPA,
4678 sm->pairwise);
4679 if (pairwise == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004680 return 0;
4681
4682 ret = os_snprintf(
4683 buf + len, buflen - len,
4684 /* TODO: dot11RSNAStatsIndex */
4685 "dot11RSNAStatsSTAAddress=" MACSTR "\n"
4686 "dot11RSNAStatsVersion=1\n"
4687 "dot11RSNAStatsSelectedPairwiseCipher=" RSN_SUITE "\n"
4688 /* TODO: dot11RSNAStatsTKIPICVErrors */
4689 "dot11RSNAStatsTKIPLocalMICFailures=%u\n"
4690 "dot11RSNAStatsTKIPRemoteMICFailures=%u\n"
4691 /* TODO: dot11RSNAStatsCCMPReplays */
4692 /* TODO: dot11RSNAStatsCCMPDecryptErrors */
4693 /* TODO: dot11RSNAStatsTKIPReplays */,
4694 MAC2STR(sm->addr),
4695 RSN_SUITE_ARG(pairwise),
4696 sm->dot11RSNAStatsTKIPLocalMICFailures,
4697 sm->dot11RSNAStatsTKIPRemoteMICFailures);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004698 if (os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004699 return len;
4700 len += ret;
4701
4702 /* Private MIB */
4703 ret = os_snprintf(buf + len, buflen - len,
Hai Shalomc3565922019-10-28 11:58:20 -07004704 "wpa=%d\n"
4705 "AKMSuiteSelector=" RSN_SUITE "\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004706 "hostapdWPAPTKState=%d\n"
4707 "hostapdWPAPTKGroupState=%d\n",
Hai Shalomc3565922019-10-28 11:58:20 -07004708 sm->wpa,
4709 RSN_SUITE_ARG(wpa_akm_to_suite(sm->wpa_key_mgmt)),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004710 sm->wpa_ptk_state,
4711 sm->wpa_ptk_group_state);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004712 if (os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004713 return len;
4714 len += ret;
4715
4716 return len;
4717}
4718
4719
4720void wpa_auth_countermeasures_start(struct wpa_authenticator *wpa_auth)
4721{
4722 if (wpa_auth)
4723 wpa_auth->dot11RSNATKIPCounterMeasuresInvoked++;
4724}
4725
4726
4727int wpa_auth_pairwise_set(struct wpa_state_machine *sm)
4728{
4729 return sm && sm->pairwise_set;
4730}
4731
4732
4733int wpa_auth_get_pairwise(struct wpa_state_machine *sm)
4734{
4735 return sm->pairwise;
4736}
4737
4738
Hai Shalom74f70d42019-02-11 14:42:39 -08004739const u8 * wpa_auth_get_pmk(struct wpa_state_machine *sm, int *len)
4740{
4741 if (!sm)
4742 return NULL;
4743 *len = sm->pmk_len;
4744 return sm->PMK;
4745}
4746
4747
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004748int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm)
4749{
Hai Shalomfdcde762020-04-02 11:19:20 -07004750 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004751 return -1;
4752 return sm->wpa_key_mgmt;
4753}
4754
4755
4756int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm)
4757{
Hai Shalomfdcde762020-04-02 11:19:20 -07004758 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004759 return 0;
4760 return sm->wpa;
4761}
4762
4763
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02004764int wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm)
4765{
4766 if (!sm || !wpa_key_mgmt_ft(sm->wpa_key_mgmt))
4767 return 0;
4768 return sm->tk_already_set;
4769}
4770
4771
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004772int wpa_auth_sta_fils_tk_already_set(struct wpa_state_machine *sm)
4773{
4774 if (!sm || !wpa_key_mgmt_fils(sm->wpa_key_mgmt))
4775 return 0;
4776 return sm->tk_already_set;
4777}
4778
4779
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004780int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm,
4781 struct rsn_pmksa_cache_entry *entry)
4782{
Hai Shalomfdcde762020-04-02 11:19:20 -07004783 if (!sm || sm->pmksa != entry)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004784 return -1;
4785 sm->pmksa = NULL;
4786 return 0;
4787}
4788
4789
4790struct rsn_pmksa_cache_entry *
4791wpa_auth_sta_get_pmksa(struct wpa_state_machine *sm)
4792{
4793 return sm ? sm->pmksa : NULL;
4794}
4795
4796
4797void wpa_auth_sta_local_mic_failure_report(struct wpa_state_machine *sm)
4798{
4799 if (sm)
4800 sm->dot11RSNAStatsTKIPLocalMICFailures++;
4801}
4802
4803
4804const u8 * wpa_auth_get_wpa_ie(struct wpa_authenticator *wpa_auth, size_t *len)
4805{
Hai Shalomfdcde762020-04-02 11:19:20 -07004806 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004807 return NULL;
4808 *len = wpa_auth->wpa_ie_len;
4809 return wpa_auth->wpa_ie;
4810}
4811
4812
4813int wpa_auth_pmksa_add(struct wpa_state_machine *sm, const u8 *pmk,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004814 unsigned int pmk_len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004815 int session_timeout, struct eapol_state_machine *eapol)
4816{
Hai Shalomfdcde762020-04-02 11:19:20 -07004817 if (!sm || sm->wpa != WPA_VERSION_WPA2 ||
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07004818 sm->wpa_auth->conf.disable_pmksa_caching)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004819 return -1;
4820
Hai Shalom81f62d82019-07-22 12:10:00 -07004821#ifdef CONFIG_IEEE80211R_AP
4822 if (pmk_len >= 2 * PMK_LEN && wpa_key_mgmt_ft(sm->wpa_key_mgmt) &&
4823 wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) &&
4824 !wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) {
4825 /* Cache MPMK/XXKey instead of initial part from MSK */
4826 pmk = pmk + PMK_LEN;
4827 pmk_len = PMK_LEN;
4828 } else
4829#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004830 if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004831 if (pmk_len > PMK_LEN_SUITE_B_192)
4832 pmk_len = PMK_LEN_SUITE_B_192;
4833 } else if (pmk_len > PMK_LEN) {
4834 pmk_len = PMK_LEN;
4835 }
4836
Hai Shalom81f62d82019-07-22 12:10:00 -07004837 wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK", pmk, pmk_len);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004838 if (pmksa_cache_auth_add(sm->wpa_auth->pmksa, pmk, pmk_len, NULL,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004839 sm->PTK.kck, sm->PTK.kck_len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004840 sm->wpa_auth->addr, sm->addr, session_timeout,
4841 eapol, sm->wpa_key_mgmt))
4842 return 0;
4843
4844 return -1;
4845}
4846
4847
4848int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth,
4849 const u8 *pmk, size_t len, const u8 *sta_addr,
4850 int session_timeout,
4851 struct eapol_state_machine *eapol)
4852{
Hai Shalomfdcde762020-04-02 11:19:20 -07004853 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004854 return -1;
4855
Hai Shalom81f62d82019-07-22 12:10:00 -07004856 wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK from preauth", pmk, len);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004857 if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, len, NULL,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004858 NULL, 0,
4859 wpa_auth->addr,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004860 sta_addr, session_timeout, eapol,
4861 WPA_KEY_MGMT_IEEE8021X))
4862 return 0;
4863
4864 return -1;
4865}
4866
4867
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004868int wpa_auth_pmksa_add_sae(struct wpa_authenticator *wpa_auth, const u8 *addr,
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004869 const u8 *pmk, const u8 *pmkid)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004870{
4871 if (wpa_auth->conf.disable_pmksa_caching)
4872 return -1;
4873
Hai Shalom81f62d82019-07-22 12:10:00 -07004874 wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK from SAE", pmk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004875 if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, PMK_LEN, pmkid,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004876 NULL, 0,
4877 wpa_auth->addr, addr, 0, NULL,
4878 WPA_KEY_MGMT_SAE))
4879 return 0;
4880
4881 return -1;
4882}
4883
4884
Roshan Pius3a1667e2018-07-03 15:17:14 -07004885void wpa_auth_add_sae_pmkid(struct wpa_state_machine *sm, const u8 *pmkid)
4886{
4887 os_memcpy(sm->pmkid, pmkid, PMKID_LEN);
4888 sm->pmkid_set = 1;
4889}
4890
4891
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004892int wpa_auth_pmksa_add2(struct wpa_authenticator *wpa_auth, const u8 *addr,
4893 const u8 *pmk, size_t pmk_len, const u8 *pmkid,
4894 int session_timeout, int akmp)
4895{
Hai Shaloma20dcd72022-02-04 13:43:00 -08004896 if (!wpa_auth || wpa_auth->conf.disable_pmksa_caching)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004897 return -1;
4898
Hai Shalom81f62d82019-07-22 12:10:00 -07004899 wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK (2)", pmk, PMK_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004900 if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, pmk_len, pmkid,
4901 NULL, 0, wpa_auth->addr, addr, session_timeout,
4902 NULL, akmp))
4903 return 0;
4904
4905 return -1;
4906}
4907
4908
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004909void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth,
4910 const u8 *sta_addr)
4911{
4912 struct rsn_pmksa_cache_entry *pmksa;
4913
Hai Shalomfdcde762020-04-02 11:19:20 -07004914 if (!wpa_auth || !wpa_auth->pmksa)
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004915 return;
4916 pmksa = pmksa_cache_auth_get(wpa_auth->pmksa, sta_addr, NULL);
4917 if (pmksa) {
4918 wpa_printf(MSG_DEBUG, "WPA: Remove PMKSA cache entry for "
4919 MACSTR " based on request", MAC2STR(sta_addr));
4920 pmksa_cache_free_entry(wpa_auth->pmksa, pmksa);
4921 }
4922}
4923
4924
Dmitry Shmidte4663042016-04-04 10:07:49 -07004925int wpa_auth_pmksa_list(struct wpa_authenticator *wpa_auth, char *buf,
4926 size_t len)
4927{
4928 if (!wpa_auth || !wpa_auth->pmksa)
4929 return 0;
4930 return pmksa_cache_auth_list(wpa_auth->pmksa, buf, len);
4931}
4932
4933
4934void wpa_auth_pmksa_flush(struct wpa_authenticator *wpa_auth)
4935{
4936 if (wpa_auth && wpa_auth->pmksa)
4937 pmksa_cache_auth_flush(wpa_auth->pmksa);
4938}
4939
4940
Paul Stewart092955c2017-02-06 09:13:09 -08004941#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
4942#ifdef CONFIG_MESH
4943
4944int wpa_auth_pmksa_list_mesh(struct wpa_authenticator *wpa_auth, const u8 *addr,
4945 char *buf, size_t len)
4946{
4947 if (!wpa_auth || !wpa_auth->pmksa)
4948 return 0;
4949
4950 return pmksa_cache_auth_list_mesh(wpa_auth->pmksa, addr, buf, len);
4951}
4952
4953
4954struct rsn_pmksa_cache_entry *
4955wpa_auth_pmksa_create_entry(const u8 *aa, const u8 *spa, const u8 *pmk,
4956 const u8 *pmkid, int expiration)
4957{
4958 struct rsn_pmksa_cache_entry *entry;
4959 struct os_reltime now;
4960
4961 entry = pmksa_cache_auth_create_entry(pmk, PMK_LEN, pmkid, NULL, 0, aa,
4962 spa, 0, NULL, WPA_KEY_MGMT_SAE);
4963 if (!entry)
4964 return NULL;
4965
4966 os_get_reltime(&now);
4967 entry->expiration = now.sec + expiration;
4968 return entry;
4969}
4970
4971
4972int wpa_auth_pmksa_add_entry(struct wpa_authenticator *wpa_auth,
4973 struct rsn_pmksa_cache_entry *entry)
4974{
4975 int ret;
4976
4977 if (!wpa_auth || !wpa_auth->pmksa)
4978 return -1;
4979
4980 ret = pmksa_cache_auth_add_entry(wpa_auth->pmksa, entry);
4981 if (ret < 0)
4982 wpa_printf(MSG_DEBUG,
4983 "RSN: Failed to store external PMKSA cache for "
4984 MACSTR, MAC2STR(entry->spa));
4985
4986 return ret;
4987}
4988
4989#endif /* CONFIG_MESH */
4990#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
4991
4992
Dmitry Shmidte4663042016-04-04 10:07:49 -07004993struct rsn_pmksa_cache_entry *
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004994wpa_auth_pmksa_get(struct wpa_authenticator *wpa_auth, const u8 *sta_addr,
4995 const u8 *pmkid)
Dmitry Shmidte4663042016-04-04 10:07:49 -07004996{
4997 if (!wpa_auth || !wpa_auth->pmksa)
4998 return NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004999 return pmksa_cache_auth_get(wpa_auth->pmksa, sta_addr, pmkid);
Dmitry Shmidte4663042016-04-04 10:07:49 -07005000}
5001
5002
5003void wpa_auth_pmksa_set_to_sm(struct rsn_pmksa_cache_entry *pmksa,
5004 struct wpa_state_machine *sm,
5005 struct wpa_authenticator *wpa_auth,
5006 u8 *pmkid, u8 *pmk)
5007{
5008 if (!sm)
5009 return;
5010
5011 sm->pmksa = pmksa;
5012 os_memcpy(pmk, pmksa->pmk, PMK_LEN);
5013 os_memcpy(pmkid, pmksa->pmkid, PMKID_LEN);
5014 os_memcpy(wpa_auth->dot11RSNAPMKIDUsed, pmksa->pmkid, PMKID_LEN);
5015}
5016
5017
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005018/*
5019 * Remove and free the group from wpa_authenticator. This is triggered by a
5020 * callback to make sure nobody is currently iterating the group list while it
5021 * gets modified.
5022 */
5023static void wpa_group_free(struct wpa_authenticator *wpa_auth,
5024 struct wpa_group *group)
5025{
5026 struct wpa_group *prev = wpa_auth->group;
5027
5028 wpa_printf(MSG_DEBUG, "WPA: Remove group state machine for VLAN-ID %d",
5029 group->vlan_id);
5030
5031 while (prev) {
5032 if (prev->next == group) {
5033 /* This never frees the special first group as needed */
5034 prev->next = group->next;
5035 os_free(group);
5036 break;
5037 }
5038 prev = prev->next;
5039 }
5040
5041}
5042
5043
5044/* Increase the reference counter for group */
5045static void wpa_group_get(struct wpa_authenticator *wpa_auth,
5046 struct wpa_group *group)
5047{
5048 /* Skip the special first group */
5049 if (wpa_auth->group == group)
5050 return;
5051
5052 group->references++;
5053}
5054
5055
5056/* Decrease the reference counter and maybe free the group */
5057static void wpa_group_put(struct wpa_authenticator *wpa_auth,
5058 struct wpa_group *group)
5059{
5060 /* Skip the special first group */
5061 if (wpa_auth->group == group)
5062 return;
5063
5064 group->references--;
5065 if (group->references)
5066 return;
5067 wpa_group_free(wpa_auth, group);
5068}
5069
5070
5071/*
5072 * Add a group that has its references counter set to zero. Caller needs to
5073 * call wpa_group_get() on the return value to mark the entry in use.
5074 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005075static struct wpa_group *
5076wpa_auth_add_group(struct wpa_authenticator *wpa_auth, int vlan_id)
5077{
5078 struct wpa_group *group;
5079
Hai Shalomfdcde762020-04-02 11:19:20 -07005080 if (!wpa_auth || !wpa_auth->group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005081 return NULL;
5082
5083 wpa_printf(MSG_DEBUG, "WPA: Add group state machine for VLAN-ID %d",
5084 vlan_id);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005085 group = wpa_group_init(wpa_auth, vlan_id, 0);
Hai Shalomfdcde762020-04-02 11:19:20 -07005086 if (!group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005087 return NULL;
5088
5089 group->next = wpa_auth->group->next;
5090 wpa_auth->group->next = group;
5091
5092 return group;
5093}
5094
5095
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005096/*
5097 * Enforce that the group state machine for the VLAN is running, increase
5098 * reference counter as interface is up. References might have been increased
5099 * even if a negative value is returned.
5100 * Returns: -1 on error (group missing, group already failed); otherwise, 0
5101 */
5102int wpa_auth_ensure_group(struct wpa_authenticator *wpa_auth, int vlan_id)
5103{
5104 struct wpa_group *group;
5105
Hai Shalomfdcde762020-04-02 11:19:20 -07005106 if (!wpa_auth)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005107 return 0;
5108
5109 group = wpa_auth->group;
5110 while (group) {
5111 if (group->vlan_id == vlan_id)
5112 break;
5113 group = group->next;
5114 }
5115
Hai Shalomfdcde762020-04-02 11:19:20 -07005116 if (!group) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005117 group = wpa_auth_add_group(wpa_auth, vlan_id);
Hai Shalomfdcde762020-04-02 11:19:20 -07005118 if (!group)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005119 return -1;
5120 }
5121
5122 wpa_printf(MSG_DEBUG,
5123 "WPA: Ensure group state machine running for VLAN ID %d",
5124 vlan_id);
5125
5126 wpa_group_get(wpa_auth, group);
5127 group->num_setup_iface++;
5128
5129 if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
5130 return -1;
5131
5132 return 0;
5133}
5134
5135
5136/*
5137 * Decrease reference counter, expected to be zero afterwards.
5138 * returns: -1 on error (group not found, group in fail state)
5139 * -2 if wpa_group is still referenced
5140 * 0 else
5141 */
5142int wpa_auth_release_group(struct wpa_authenticator *wpa_auth, int vlan_id)
5143{
5144 struct wpa_group *group;
5145 int ret = 0;
5146
Hai Shalomfdcde762020-04-02 11:19:20 -07005147 if (!wpa_auth)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005148 return 0;
5149
5150 group = wpa_auth->group;
5151 while (group) {
5152 if (group->vlan_id == vlan_id)
5153 break;
5154 group = group->next;
5155 }
5156
Hai Shalomfdcde762020-04-02 11:19:20 -07005157 if (!group)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005158 return -1;
5159
5160 wpa_printf(MSG_DEBUG,
5161 "WPA: Try stopping group state machine for VLAN ID %d",
5162 vlan_id);
5163
5164 if (group->num_setup_iface <= 0) {
5165 wpa_printf(MSG_ERROR,
5166 "WPA: wpa_auth_release_group called more often than wpa_auth_ensure_group for VLAN ID %d, skipping.",
5167 vlan_id);
5168 return -1;
5169 }
5170 group->num_setup_iface--;
5171
5172 if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
5173 ret = -1;
5174
5175 if (group->references > 1) {
5176 wpa_printf(MSG_DEBUG,
5177 "WPA: Cannot stop group state machine for VLAN ID %d as references are still hold",
5178 vlan_id);
5179 ret = -2;
5180 }
5181
5182 wpa_group_put(wpa_auth, group);
5183
5184 return ret;
5185}
5186
5187
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005188int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id)
5189{
5190 struct wpa_group *group;
5191
Hai Shalomfdcde762020-04-02 11:19:20 -07005192 if (!sm || !sm->wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005193 return 0;
5194
5195 group = sm->wpa_auth->group;
5196 while (group) {
5197 if (group->vlan_id == vlan_id)
5198 break;
5199 group = group->next;
5200 }
5201
Hai Shalomfdcde762020-04-02 11:19:20 -07005202 if (!group) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005203 group = wpa_auth_add_group(sm->wpa_auth, vlan_id);
Hai Shalomfdcde762020-04-02 11:19:20 -07005204 if (!group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005205 return -1;
5206 }
5207
5208 if (sm->group == group)
5209 return 0;
5210
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005211 if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
5212 return -1;
5213
Hai Shalomfdcde762020-04-02 11:19:20 -07005214 wpa_printf(MSG_DEBUG, "WPA: Moving STA " MACSTR
5215 " to use group state machine for VLAN ID %d",
5216 MAC2STR(sm->addr), vlan_id);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005217
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005218 wpa_group_get(sm->wpa_auth, group);
5219 wpa_group_put(sm->wpa_auth, sm->group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005220 sm->group = group;
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005221
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005222 return 0;
5223}
5224
5225
5226void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth,
5227 struct wpa_state_machine *sm, int ack)
5228{
Hai Shalomfdcde762020-04-02 11:19:20 -07005229 if (!wpa_auth || !sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005230 return;
5231 wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key TX status for STA " MACSTR
5232 " ack=%d", MAC2STR(sm->addr), ack);
5233 if (sm->pending_1_of_4_timeout && ack) {
5234 /*
5235 * Some deployed supplicant implementations update their SNonce
5236 * for each EAPOL-Key 2/4 message even within the same 4-way
5237 * handshake and then fail to use the first SNonce when
5238 * deriving the PTK. This results in unsuccessful 4-way
5239 * handshake whenever the relatively short initial timeout is
5240 * reached and EAPOL-Key 1/4 is retransmitted. Try to work
5241 * around this by increasing the timeout now that we know that
5242 * the station has received the frame.
5243 */
5244 int timeout_ms = eapol_key_timeout_subseq;
Hai Shalomfdcde762020-04-02 11:19:20 -07005245 wpa_printf(MSG_DEBUG,
5246 "WPA: Increase initial EAPOL-Key 1/4 timeout by %u ms because of acknowledged frame",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005247 timeout_ms);
5248 eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm);
5249 eloop_register_timeout(timeout_ms / 1000,
5250 (timeout_ms % 1000) * 1000,
5251 wpa_send_eapol_timeout, wpa_auth, sm);
5252 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005253
5254#ifdef CONFIG_TESTING_OPTIONS
5255 if (sm->eapol_status_cb) {
5256 sm->eapol_status_cb(sm->eapol_status_cb_ctx1,
5257 sm->eapol_status_cb_ctx2);
5258 sm->eapol_status_cb = NULL;
5259 }
5260#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005261}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005262
5263
5264int wpa_auth_uses_sae(struct wpa_state_machine *sm)
5265{
Hai Shalomfdcde762020-04-02 11:19:20 -07005266 if (!sm)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005267 return 0;
5268 return wpa_key_mgmt_sae(sm->wpa_key_mgmt);
5269}
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005270
5271
5272int wpa_auth_uses_ft_sae(struct wpa_state_machine *sm)
5273{
Hai Shalomfdcde762020-04-02 11:19:20 -07005274 if (!sm)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005275 return 0;
5276 return sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_SAE;
5277}
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08005278
5279
5280#ifdef CONFIG_P2P
5281int wpa_auth_get_ip_addr(struct wpa_state_machine *sm, u8 *addr)
5282{
Hai Shalomfdcde762020-04-02 11:19:20 -07005283 if (!sm || WPA_GET_BE32(sm->ip_addr) == 0)
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08005284 return -1;
5285 os_memcpy(addr, sm->ip_addr, 4);
5286 return 0;
5287}
5288#endif /* CONFIG_P2P */
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08005289
5290
5291int wpa_auth_radius_das_disconnect_pmksa(struct wpa_authenticator *wpa_auth,
5292 struct radius_das_attrs *attr)
5293{
5294 return pmksa_cache_auth_radius_das_disconnect(wpa_auth->pmksa, attr);
5295}
Dmitry Shmidt7f656022015-02-25 14:36:37 -08005296
5297
5298void wpa_auth_reconfig_group_keys(struct wpa_authenticator *wpa_auth)
5299{
5300 struct wpa_group *group;
5301
5302 if (!wpa_auth)
5303 return;
5304 for (group = wpa_auth->group; group; group = group->next)
5305 wpa_group_config_group_keys(wpa_auth, group);
5306}
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005307
5308
5309#ifdef CONFIG_FILS
5310
5311struct wpa_auth_fils_iter_data {
5312 struct wpa_authenticator *auth;
5313 const u8 *cache_id;
5314 struct rsn_pmksa_cache_entry *pmksa;
5315 const u8 *spa;
5316 const u8 *pmkid;
5317};
5318
5319
5320static int wpa_auth_fils_iter(struct wpa_authenticator *a, void *ctx)
5321{
5322 struct wpa_auth_fils_iter_data *data = ctx;
5323
5324 if (a == data->auth || !a->conf.fils_cache_id_set ||
5325 os_memcmp(a->conf.fils_cache_id, data->cache_id,
5326 FILS_CACHE_ID_LEN) != 0)
5327 return 0;
5328 data->pmksa = pmksa_cache_auth_get(a->pmksa, data->spa, data->pmkid);
5329 return data->pmksa != NULL;
5330}
5331
5332
5333struct rsn_pmksa_cache_entry *
5334wpa_auth_pmksa_get_fils_cache_id(struct wpa_authenticator *wpa_auth,
5335 const u8 *sta_addr, const u8 *pmkid)
5336{
5337 struct wpa_auth_fils_iter_data idata;
5338
5339 if (!wpa_auth->conf.fils_cache_id_set)
5340 return NULL;
5341 idata.auth = wpa_auth;
5342 idata.cache_id = wpa_auth->conf.fils_cache_id;
5343 idata.pmksa = NULL;
5344 idata.spa = sta_addr;
5345 idata.pmkid = pmkid;
5346 wpa_auth_for_each_auth(wpa_auth, wpa_auth_fils_iter, &idata);
5347 return idata.pmksa;
5348}
5349
5350
5351#ifdef CONFIG_IEEE80211R_AP
Roshan Pius3a1667e2018-07-03 15:17:14 -07005352int wpa_auth_write_fte(struct wpa_authenticator *wpa_auth, int use_sha384,
5353 u8 *buf, size_t len)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005354{
5355 struct wpa_auth_config *conf = &wpa_auth->conf;
5356
Roshan Pius3a1667e2018-07-03 15:17:14 -07005357 return wpa_write_ftie(conf, use_sha384, conf->r0_key_holder,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005358 conf->r0_key_holder_len,
Hai Shalomfdcde762020-04-02 11:19:20 -07005359 NULL, NULL, buf, len, NULL, 0, 0);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005360}
5361#endif /* CONFIG_IEEE80211R_AP */
5362
5363
5364void wpa_auth_get_fils_aead_params(struct wpa_state_machine *sm,
5365 u8 *fils_anonce, u8 *fils_snonce,
5366 u8 *fils_kek, size_t *fils_kek_len)
5367{
5368 os_memcpy(fils_anonce, sm->ANonce, WPA_NONCE_LEN);
5369 os_memcpy(fils_snonce, sm->SNonce, WPA_NONCE_LEN);
5370 os_memcpy(fils_kek, sm->PTK.kek, WPA_KEK_MAX_LEN);
5371 *fils_kek_len = sm->PTK.kek_len;
5372}
5373
Hai Shalom81f62d82019-07-22 12:10:00 -07005374
5375void wpa_auth_add_fils_pmk_pmkid(struct wpa_state_machine *sm, const u8 *pmk,
5376 size_t pmk_len, const u8 *pmkid)
5377{
5378 os_memcpy(sm->PMK, pmk, pmk_len);
5379 sm->pmk_len = pmk_len;
5380 os_memcpy(sm->pmkid, pmkid, PMKID_LEN);
5381 sm->pmkid_set = 1;
5382}
5383
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005384#endif /* CONFIG_FILS */
5385
5386
Hai Shalom021b0b52019-04-10 11:17:58 -07005387void wpa_auth_set_auth_alg(struct wpa_state_machine *sm, u16 auth_alg)
5388{
5389 if (sm)
5390 sm->auth_alg = auth_alg;
5391}
5392
5393
5394#ifdef CONFIG_DPP2
5395void wpa_auth_set_dpp_z(struct wpa_state_machine *sm, const struct wpabuf *z)
5396{
5397 if (sm) {
5398 wpabuf_clear_free(sm->dpp_z);
5399 sm->dpp_z = z ? wpabuf_dup(z) : NULL;
5400 }
5401}
5402#endif /* CONFIG_DPP2 */
5403
5404
Hai Shalom899fcc72020-10-19 14:38:18 -07005405void wpa_auth_set_transition_disable(struct wpa_authenticator *wpa_auth,
5406 u8 val)
5407{
5408 if (wpa_auth)
5409 wpa_auth->conf.transition_disable = val;
5410}
5411
5412
Roshan Pius3a1667e2018-07-03 15:17:14 -07005413#ifdef CONFIG_TESTING_OPTIONS
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005414
5415int wpa_auth_resend_m1(struct wpa_state_machine *sm, int change_anonce,
5416 void (*cb)(void *ctx1, void *ctx2),
5417 void *ctx1, void *ctx2)
5418{
5419 const u8 *anonce = sm->ANonce;
5420 u8 anonce_buf[WPA_NONCE_LEN];
5421
5422 if (change_anonce) {
5423 if (random_get_bytes(anonce_buf, WPA_NONCE_LEN))
5424 return -1;
5425 anonce = anonce_buf;
5426 }
5427
5428 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
5429 "sending 1/4 msg of 4-Way Handshake (TESTING)");
5430 wpa_send_eapol(sm->wpa_auth, sm,
5431 WPA_KEY_INFO_ACK | WPA_KEY_INFO_KEY_TYPE, NULL,
5432 anonce, NULL, 0, 0, 0);
5433 return 0;
5434}
5435
5436
5437int wpa_auth_resend_m3(struct wpa_state_machine *sm,
5438 void (*cb)(void *ctx1, void *ctx2),
5439 void *ctx1, void *ctx2)
5440{
Roshan Pius3a1667e2018-07-03 15:17:14 -07005441 u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde, *pos;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005442 u8 *opos;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005443 size_t gtk_len, kde_len;
Hai Shalom899fcc72020-10-19 14:38:18 -07005444 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005445 struct wpa_group *gsm = sm->group;
5446 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07005447 int wpa_ie_len, secure, gtkidx, encr = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07005448 u8 hdr[2];
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005449
5450 /* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, [MDIE],
Hai Shalomfdcde762020-04-02 11:19:20 -07005451 GTK[GN], IGTK, [BIGTK], [FTIE], [TIE * 2])
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005452 */
5453
5454 /* Use 0 RSC */
5455 os_memset(rsc, 0, WPA_KEY_RSC_LEN);
5456 /* If FT is used, wpa_auth->wpa_ie includes both RSNIE and MDIE */
5457 wpa_ie = sm->wpa_auth->wpa_ie;
5458 wpa_ie_len = sm->wpa_auth->wpa_ie_len;
5459 if (sm->wpa == WPA_VERSION_WPA &&
5460 (sm->wpa_auth->conf.wpa & WPA_PROTO_RSN) &&
5461 wpa_ie_len > wpa_ie[1] + 2 && wpa_ie[0] == WLAN_EID_RSN) {
5462 /* WPA-only STA, remove RSN IE and possible MDIE */
5463 wpa_ie = wpa_ie + wpa_ie[1] + 2;
Hai Shalom60840252021-02-19 19:02:11 -08005464 if (wpa_ie[0] == WLAN_EID_RSNX)
5465 wpa_ie = wpa_ie + wpa_ie[1] + 2;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005466 if (wpa_ie[0] == WLAN_EID_MOBILITY_DOMAIN)
5467 wpa_ie = wpa_ie + wpa_ie[1] + 2;
5468 wpa_ie_len = wpa_ie[1] + 2;
5469 }
5470 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
5471 "sending 3/4 msg of 4-Way Handshake (TESTING)");
5472 if (sm->wpa == WPA_VERSION_WPA2) {
5473 /* WPA2 send GTK in the 4-way handshake */
5474 secure = 1;
5475 gtk = gsm->GTK[gsm->GN - 1];
5476 gtk_len = gsm->GTK_len;
Hai Shalomc3565922019-10-28 11:58:20 -07005477 gtkidx = gsm->GN;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005478 _rsc = rsc;
5479 encr = 1;
5480 } else {
5481 /* WPA does not include GTK in msg 3/4 */
5482 secure = 0;
5483 gtk = NULL;
5484 gtk_len = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005485 _rsc = NULL;
5486 if (sm->rx_eapol_key_secure) {
5487 /*
5488 * It looks like Windows 7 supplicant tries to use
5489 * Secure bit in msg 2/4 after having reported Michael
5490 * MIC failure and it then rejects the 4-way handshake
5491 * if msg 3/4 does not set Secure bit. Work around this
5492 * by setting the Secure bit here even in the case of
5493 * WPA if the supplicant used it first.
5494 */
5495 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07005496 "STA used Secure bit in WPA msg 2/4 - set Secure for 3/4 as workaround");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005497 secure = 1;
5498 }
5499 }
5500
Hai Shalom74f70d42019-02-11 14:42:39 -08005501 kde_len = wpa_ie_len + ieee80211w_kde_len(sm) + ocv_oci_len(sm);
Hai Shalomfdcde762020-04-02 11:19:20 -07005502
5503 if (sm->use_ext_key_id)
5504 kde_len += 2 + RSN_SELECTOR_LEN + 2;
5505
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005506 if (gtk)
5507 kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len;
5508#ifdef CONFIG_IEEE80211R_AP
5509 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
5510 kde_len += 2 + PMKID_LEN; /* PMKR1Name into RSN IE */
5511 kde_len += 300; /* FTIE + 2 * TIE */
5512 }
5513#endif /* CONFIG_IEEE80211R_AP */
5514 kde = os_malloc(kde_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07005515 if (!kde)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005516 return -1;
5517
5518 pos = kde;
5519 os_memcpy(pos, wpa_ie, wpa_ie_len);
5520 pos += wpa_ie_len;
5521#ifdef CONFIG_IEEE80211R_AP
5522 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
5523 int res;
5524 size_t elen;
5525
5526 elen = pos - kde;
5527 res = wpa_insert_pmkid(kde, &elen, sm->pmk_r1_name);
5528 if (res < 0) {
Hai Shalomfdcde762020-04-02 11:19:20 -07005529 wpa_printf(MSG_ERROR,
5530 "FT: Failed to insert PMKR1Name into RSN IE in EAPOL-Key data");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005531 os_free(kde);
5532 return -1;
5533 }
5534 pos -= wpa_ie_len;
5535 pos += elen;
5536 }
5537#endif /* CONFIG_IEEE80211R_AP */
Hai Shalomfdcde762020-04-02 11:19:20 -07005538 hdr[1] = 0;
5539
5540 if (sm->use_ext_key_id) {
5541 hdr[0] = sm->keyidx_active & 0x01;
5542 pos = wpa_add_kde(pos, RSN_KEY_DATA_KEYID, hdr, 2, NULL, 0);
5543 }
5544
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005545 if (gtk) {
Hai Shalomc3565922019-10-28 11:58:20 -07005546 hdr[0] = gtkidx & 0x03;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005547 pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
5548 gtk, gtk_len);
5549 }
5550 opos = pos;
5551 pos = ieee80211w_kde_add(sm, pos);
Roshan Pius3a1667e2018-07-03 15:17:14 -07005552 if (pos - opos >= 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN) {
5553 /* skip KDE header and keyid */
5554 opos += 2 + RSN_SELECTOR_LEN + 2;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005555 os_memset(opos, 0, 6); /* clear PN */
5556 }
Hai Shalom899fcc72020-10-19 14:38:18 -07005557 if (ocv_oci_add(sm, &pos, conf->oci_freq_override_eapol_m3) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -08005558 os_free(kde);
5559 return -1;
5560 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005561
5562#ifdef CONFIG_IEEE80211R_AP
5563 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
5564 int res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005565
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005566 if (sm->assoc_resp_ftie &&
5567 kde + kde_len - pos >= 2 + sm->assoc_resp_ftie[1]) {
5568 os_memcpy(pos, sm->assoc_resp_ftie,
5569 2 + sm->assoc_resp_ftie[1]);
5570 res = 2 + sm->assoc_resp_ftie[1];
5571 } else {
Roshan Pius3a1667e2018-07-03 15:17:14 -07005572 int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt);
5573
5574 res = wpa_write_ftie(conf, use_sha384,
5575 conf->r0_key_holder,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005576 conf->r0_key_holder_len,
5577 NULL, NULL, pos,
5578 kde + kde_len - pos,
Hai Shalomfdcde762020-04-02 11:19:20 -07005579 NULL, 0, 0);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005580 }
5581 if (res < 0) {
Hai Shalomfdcde762020-04-02 11:19:20 -07005582 wpa_printf(MSG_ERROR,
5583 "FT: Failed to insert FTIE into EAPOL-Key Key Data");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005584 os_free(kde);
5585 return -1;
5586 }
5587 pos += res;
5588
5589 /* TIE[ReassociationDeadline] (TU) */
5590 *pos++ = WLAN_EID_TIMEOUT_INTERVAL;
5591 *pos++ = 5;
5592 *pos++ = WLAN_TIMEOUT_REASSOC_DEADLINE;
5593 WPA_PUT_LE32(pos, conf->reassociation_deadline);
5594 pos += 4;
5595
5596 /* TIE[KeyLifetime] (seconds) */
5597 *pos++ = WLAN_EID_TIMEOUT_INTERVAL;
5598 *pos++ = 5;
5599 *pos++ = WLAN_TIMEOUT_KEY_LIFETIME;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005600 WPA_PUT_LE32(pos, conf->r0_key_lifetime);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005601 pos += 4;
5602 }
5603#endif /* CONFIG_IEEE80211R_AP */
5604
5605 wpa_send_eapol(sm->wpa_auth, sm,
5606 (secure ? WPA_KEY_INFO_SECURE : 0) |
5607 (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
5608 WPA_KEY_INFO_MIC : 0) |
5609 WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL |
5610 WPA_KEY_INFO_KEY_TYPE,
Hai Shalomc3565922019-10-28 11:58:20 -07005611 _rsc, sm->ANonce, kde, pos - kde, 0, encr);
Sunil Ravia04bd252022-05-02 22:54:18 -07005612 bin_clear_free(kde, kde_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005613 return 0;
5614}
5615
5616
5617int wpa_auth_resend_group_m1(struct wpa_state_machine *sm,
5618 void (*cb)(void *ctx1, void *ctx2),
5619 void *ctx1, void *ctx2)
5620{
5621 u8 rsc[WPA_KEY_RSC_LEN];
Hai Shalom899fcc72020-10-19 14:38:18 -07005622 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005623 struct wpa_group *gsm = sm->group;
5624 const u8 *kde;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005625 u8 *kde_buf = NULL, *pos, hdr[2];
Roshan Pius3a1667e2018-07-03 15:17:14 -07005626 u8 *opos;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005627 size_t kde_len;
5628 u8 *gtk;
5629
5630 /* Send EAPOL(1, 1, 1, !Pair, G, RSC, GNonce, MIC(PTK), GTK[GN]) */
5631 os_memset(rsc, 0, WPA_KEY_RSC_LEN);
5632 /* Use 0 RSC */
5633 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
5634 "sending 1/2 msg of Group Key Handshake (TESTING)");
5635
5636 gtk = gsm->GTK[gsm->GN - 1];
5637 if (sm->wpa == WPA_VERSION_WPA2) {
5638 kde_len = 2 + RSN_SELECTOR_LEN + 2 + gsm->GTK_len +
Hai Shalom74f70d42019-02-11 14:42:39 -08005639 ieee80211w_kde_len(sm) + ocv_oci_len(sm);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005640 kde_buf = os_malloc(kde_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07005641 if (!kde_buf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005642 return -1;
5643
5644 kde = pos = kde_buf;
5645 hdr[0] = gsm->GN & 0x03;
5646 hdr[1] = 0;
5647 pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
5648 gtk, gsm->GTK_len);
5649 opos = pos;
5650 pos = ieee80211w_kde_add(sm, pos);
Roshan Pius3a1667e2018-07-03 15:17:14 -07005651 if (pos - opos >=
5652 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN) {
5653 /* skip KDE header and keyid */
5654 opos += 2 + RSN_SELECTOR_LEN + 2;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005655 os_memset(opos, 0, 6); /* clear PN */
5656 }
Hai Shalom899fcc72020-10-19 14:38:18 -07005657 if (ocv_oci_add(sm, &pos,
5658 conf->oci_freq_override_eapol_g1) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -08005659 os_free(kde_buf);
5660 return -1;
5661 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005662 kde_len = pos - kde;
5663 } else {
5664 kde = gtk;
5665 kde_len = gsm->GTK_len;
5666 }
5667
5668 sm->eapol_status_cb = cb;
5669 sm->eapol_status_cb_ctx1 = ctx1;
5670 sm->eapol_status_cb_ctx2 = ctx2;
5671
5672 wpa_send_eapol(sm->wpa_auth, sm,
5673 WPA_KEY_INFO_SECURE |
5674 (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
5675 WPA_KEY_INFO_MIC : 0) |
5676 WPA_KEY_INFO_ACK |
5677 (!sm->Pair ? WPA_KEY_INFO_INSTALL : 0),
5678 rsc, NULL, kde, kde_len, gsm->GN, 1);
5679
Sunil Ravia04bd252022-05-02 22:54:18 -07005680 bin_clear_free(kde_buf, kde_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005681 return 0;
5682}
5683
Roshan Pius3a1667e2018-07-03 15:17:14 -07005684
5685int wpa_auth_rekey_gtk(struct wpa_authenticator *wpa_auth)
5686{
5687 if (!wpa_auth)
5688 return -1;
5689 eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL);
5690 return eloop_register_timeout(0, 0, wpa_rekey_gtk, wpa_auth, NULL);
5691}
5692
Hai Shalomb755a2a2020-04-23 21:49:02 -07005693
Hai Shaloma20dcd72022-02-04 13:43:00 -08005694int wpa_auth_rekey_ptk(struct wpa_authenticator *wpa_auth,
5695 struct wpa_state_machine *sm)
5696{
5697 if (!wpa_auth || !sm)
5698 return -1;
5699 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "rekeying PTK");
5700 wpa_request_new_ptk(sm);
5701 wpa_sm_step(sm);
5702 return 0;
5703}
5704
5705
Hai Shalomb755a2a2020-04-23 21:49:02 -07005706void wpa_auth_set_ft_rsnxe_used(struct wpa_authenticator *wpa_auth, int val)
5707{
5708 if (wpa_auth)
5709 wpa_auth->conf.ft_rsnxe_used = val;
5710}
5711
Hai Shalom899fcc72020-10-19 14:38:18 -07005712
5713void wpa_auth_set_ocv_override_freq(struct wpa_authenticator *wpa_auth,
5714 enum wpa_auth_ocv_override_frame frame,
5715 unsigned int freq)
5716{
5717 if (!wpa_auth)
5718 return;
5719 switch (frame) {
5720 case WPA_AUTH_OCV_OVERRIDE_EAPOL_M3:
5721 wpa_auth->conf.oci_freq_override_eapol_m3 = freq;
5722 break;
5723 case WPA_AUTH_OCV_OVERRIDE_EAPOL_G1:
5724 wpa_auth->conf.oci_freq_override_eapol_g1 = freq;
5725 break;
5726 case WPA_AUTH_OCV_OVERRIDE_FT_ASSOC:
5727 wpa_auth->conf.oci_freq_override_ft_assoc = freq;
5728 break;
5729 case WPA_AUTH_OCV_OVERRIDE_FILS_ASSOC:
5730 wpa_auth->conf.oci_freq_override_fils_assoc = freq;
5731 break;
5732 }
5733}
5734
Kai Shie75b0652020-11-24 20:31:29 -08005735void wpa_auth_set_skip_send_eapol(struct wpa_authenticator *wpa_auth,
5736 u8 val)
5737{
5738 if (wpa_auth)
5739 wpa_auth->conf.skip_send_eapol = val;
5740}
5741
5742void wpa_auth_set_enable_eapol_large_timeout(struct wpa_authenticator *wpa_auth,
5743 u8 val)
5744{
5745 if (wpa_auth)
5746 wpa_auth->conf.enable_eapol_large_timeout = val;
5747}
5748
5749
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005750#endif /* CONFIG_TESTING_OPTIONS */
Sunil Ravia04bd252022-05-02 22:54:18 -07005751
5752
5753void wpa_auth_sta_radius_psk_resp(struct wpa_state_machine *sm, bool success)
5754{
5755 if (!sm->waiting_radius_psk) {
5756 wpa_printf(MSG_DEBUG,
5757 "Ignore RADIUS PSK response for " MACSTR
5758 " that did not wait one",
5759 MAC2STR(sm->addr));
5760 return;
5761 }
5762
5763 wpa_printf(MSG_DEBUG, "RADIUS PSK response for " MACSTR " (%s)",
5764 MAC2STR(sm->addr), success ? "success" : "fail");
5765 sm->waiting_radius_psk = 0;
5766
5767 if (success) {
5768 /* Try to process the EAPOL-Key msg 2/4 again */
5769 sm->EAPOLKeyReceived = true;
5770 } else {
5771 sm->Disconnect = true;
5772 }
5773
5774 eloop_register_timeout(0, 0, wpa_sm_call_step, sm, NULL);
5775}