blob: bb7ee254d7294fa724daea07c153415085afbb15 [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
Hai Shalom021b0b52019-04-10 11:17:58 -07003 * Copyright (c) 2004-2019, 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;
610 os_free(prev);
611 }
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
1488 sm->pending_1_of_4_timeout = 0;
1489 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "EAPOL-Key timeout");
Hai Shalome21d4e82020-04-29 16:34:06 -07001490 sm->TimeoutEvt = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001491 wpa_sm_step(sm);
1492}
1493
1494
1495void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
1496 struct wpa_state_machine *sm, int key_info,
1497 const u8 *key_rsc, const u8 *nonce,
1498 const u8 *kde, size_t kde_len,
1499 int keyidx, int encr, int force_version)
1500{
Hai Shalomfdcde762020-04-02 11:19:20 -07001501 struct wpa_auth_config *conf = &wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001502 struct ieee802_1x_hdr *hdr;
1503 struct wpa_eapol_key *key;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001504 size_t len, mic_len, keyhdrlen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001505 int alg;
1506 int key_data_len, pad_len = 0;
1507 u8 *buf, *pos;
1508 int version, pairwise;
1509 int i;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001510 u8 *key_mic, *key_data;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001511
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001512 mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001513 keyhdrlen = sizeof(*key) + mic_len + 2;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001514
1515 len = sizeof(struct ieee802_1x_hdr) + keyhdrlen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001516
1517 if (force_version)
1518 version = force_version;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001519 else if (wpa_use_akm_defined(sm->wpa_key_mgmt))
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001520 version = WPA_KEY_INFO_TYPE_AKM_DEFINED;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001521 else if (wpa_use_cmac(sm->wpa_key_mgmt))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001522 version = WPA_KEY_INFO_TYPE_AES_128_CMAC;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001523 else if (sm->pairwise != WPA_CIPHER_TKIP)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001524 version = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;
1525 else
1526 version = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
1527
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001528 pairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001529
Hai Shalomfdcde762020-04-02 11:19:20 -07001530 wpa_printf(MSG_DEBUG,
1531 "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 -07001532 version,
1533 (key_info & WPA_KEY_INFO_SECURE) ? 1 : 0,
1534 (key_info & WPA_KEY_INFO_MIC) ? 1 : 0,
1535 (key_info & WPA_KEY_INFO_ACK) ? 1 : 0,
1536 (key_info & WPA_KEY_INFO_INSTALL) ? 1 : 0,
Hai Shalomfdcde762020-04-02 11:19:20 -07001537 pairwise, kde_len, keyidx, encr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001538
1539 key_data_len = kde_len;
1540
1541 if ((version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
Roshan Pius3a1667e2018-07-03 15:17:14 -07001542 wpa_use_aes_key_wrap(sm->wpa_key_mgmt) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001543 version == WPA_KEY_INFO_TYPE_AES_128_CMAC) && encr) {
1544 pad_len = key_data_len % 8;
1545 if (pad_len)
1546 pad_len = 8 - pad_len;
1547 key_data_len += pad_len + 8;
1548 }
1549
1550 len += key_data_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001551 if (!mic_len && encr)
1552 len += AES_BLOCK_SIZE;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001553
1554 hdr = os_zalloc(len);
Hai Shalomfdcde762020-04-02 11:19:20 -07001555 if (!hdr)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001556 return;
Hai Shalomfdcde762020-04-02 11:19:20 -07001557 hdr->version = conf->eapol_version;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001558 hdr->type = IEEE802_1X_TYPE_EAPOL_KEY;
1559 hdr->length = host_to_be16(len - sizeof(*hdr));
1560 key = (struct wpa_eapol_key *) (hdr + 1);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001561 key_mic = (u8 *) (key + 1);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001562 key_data = ((u8 *) (hdr + 1)) + keyhdrlen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001563
1564 key->type = sm->wpa == WPA_VERSION_WPA2 ?
1565 EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
1566 key_info |= version;
1567 if (encr && sm->wpa == WPA_VERSION_WPA2)
1568 key_info |= WPA_KEY_INFO_ENCR_KEY_DATA;
1569 if (sm->wpa != WPA_VERSION_WPA2)
1570 key_info |= keyidx << WPA_KEY_INFO_KEY_INDEX_SHIFT;
1571 WPA_PUT_BE16(key->key_info, key_info);
1572
Hai Shalomfdcde762020-04-02 11:19:20 -07001573 alg = pairwise ? sm->pairwise : conf->wpa_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001574 if (sm->wpa == WPA_VERSION_WPA2 && !pairwise)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001575 WPA_PUT_BE16(key->key_length, 0);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001576 else
1577 WPA_PUT_BE16(key->key_length, wpa_cipher_key_len(alg));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001578
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001579 for (i = RSNA_MAX_EAPOL_RETRIES - 1; i > 0; i--) {
1580 sm->key_replay[i].valid = sm->key_replay[i - 1].valid;
1581 os_memcpy(sm->key_replay[i].counter,
1582 sm->key_replay[i - 1].counter,
1583 WPA_REPLAY_COUNTER_LEN);
1584 }
1585 inc_byte_array(sm->key_replay[0].counter, WPA_REPLAY_COUNTER_LEN);
1586 os_memcpy(key->replay_counter, sm->key_replay[0].counter,
1587 WPA_REPLAY_COUNTER_LEN);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001588 wpa_hexdump(MSG_DEBUG, "WPA: Replay Counter",
1589 key->replay_counter, WPA_REPLAY_COUNTER_LEN);
Hai Shalome21d4e82020-04-29 16:34:06 -07001590 sm->key_replay[0].valid = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001591
1592 if (nonce)
1593 os_memcpy(key->key_nonce, nonce, WPA_NONCE_LEN);
1594
1595 if (key_rsc)
1596 os_memcpy(key->key_rsc, key_rsc, WPA_KEY_RSC_LEN);
1597
1598 if (kde && !encr) {
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001599 os_memcpy(key_data, kde, kde_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001600 WPA_PUT_BE16(key_mic + mic_len, kde_len);
1601#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07001602 } else if (!mic_len && kde) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001603 const u8 *aad[1];
1604 size_t aad_len[1];
1605
1606 WPA_PUT_BE16(key_mic, AES_BLOCK_SIZE + kde_len);
1607 wpa_hexdump_key(MSG_DEBUG, "Plaintext EAPOL-Key Key Data",
1608 kde, kde_len);
1609
1610 wpa_hexdump_key(MSG_DEBUG, "WPA: KEK",
1611 sm->PTK.kek, sm->PTK.kek_len);
1612 /* AES-SIV AAD from EAPOL protocol version field (inclusive) to
1613 * to Key Data (exclusive). */
1614 aad[0] = (u8 *) hdr;
1615 aad_len[0] = key_mic + 2 - (u8 *) hdr;
1616 if (aes_siv_encrypt(sm->PTK.kek, sm->PTK.kek_len, kde, kde_len,
1617 1, aad, aad_len, key_mic + 2) < 0) {
1618 wpa_printf(MSG_DEBUG, "WPA: AES-SIV encryption failed");
1619 return;
1620 }
1621
1622 wpa_hexdump(MSG_DEBUG, "WPA: Encrypted Key Data from SIV",
1623 key_mic + 2, AES_BLOCK_SIZE + kde_len);
1624#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001625 } else if (encr && kde) {
1626 buf = os_zalloc(key_data_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07001627 if (!buf) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001628 os_free(hdr);
1629 return;
1630 }
1631 pos = buf;
1632 os_memcpy(pos, kde, kde_len);
1633 pos += kde_len;
1634
1635 if (pad_len)
1636 *pos++ = 0xdd;
1637
1638 wpa_hexdump_key(MSG_DEBUG, "Plaintext EAPOL-Key Key Data",
1639 buf, key_data_len);
1640 if (version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
Roshan Pius3a1667e2018-07-03 15:17:14 -07001641 wpa_use_aes_key_wrap(sm->wpa_key_mgmt) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001642 version == WPA_KEY_INFO_TYPE_AES_128_CMAC) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001643 wpa_printf(MSG_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07001644 "WPA: Encrypt Key Data using AES-WRAP (KEK length %zu)",
1645 sm->PTK.kek_len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001646 if (aes_wrap(sm->PTK.kek, sm->PTK.kek_len,
1647 (key_data_len - 8) / 8, buf, key_data)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001648 os_free(hdr);
1649 os_free(buf);
1650 return;
1651 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001652 WPA_PUT_BE16(key_mic + mic_len, key_data_len);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001653#ifndef CONFIG_NO_RC4
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001654 } else if (sm->PTK.kek_len == 16) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001655 u8 ek[32];
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001656
1657 wpa_printf(MSG_DEBUG,
1658 "WPA: Encrypt Key Data using RC4");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001659 os_memcpy(key->key_iv,
1660 sm->group->Counter + WPA_NONCE_LEN - 16, 16);
1661 inc_byte_array(sm->group->Counter, WPA_NONCE_LEN);
1662 os_memcpy(ek, key->key_iv, 16);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001663 os_memcpy(ek + 16, sm->PTK.kek, sm->PTK.kek_len);
1664 os_memcpy(key_data, buf, key_data_len);
1665 rc4_skip(ek, 32, 256, key_data, key_data_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001666 WPA_PUT_BE16(key_mic + mic_len, key_data_len);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001667#endif /* CONFIG_NO_RC4 */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001668 } else {
1669 os_free(hdr);
1670 os_free(buf);
1671 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001672 }
1673 os_free(buf);
1674 }
1675
1676 if (key_info & WPA_KEY_INFO_MIC) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001677 if (!sm->PTK_valid || !mic_len) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001678 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07001679 "PTK not valid when sending EAPOL-Key frame");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001680 os_free(hdr);
1681 return;
1682 }
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001683
Roshan Pius3a1667e2018-07-03 15:17:14 -07001684 if (wpa_eapol_key_mic(sm->PTK.kck, sm->PTK.kck_len,
1685 sm->wpa_key_mgmt, version,
1686 (u8 *) hdr, len, key_mic) < 0) {
1687 os_free(hdr);
1688 return;
1689 }
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001690#ifdef CONFIG_TESTING_OPTIONS
1691 if (!pairwise &&
Hai Shalomfdcde762020-04-02 11:19:20 -07001692 conf->corrupt_gtk_rekey_mic_probability > 0.0 &&
1693 drand48() < conf->corrupt_gtk_rekey_mic_probability) {
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001694 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
1695 "Corrupting group EAPOL-Key Key MIC");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001696 key_mic[0]++;
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001697 }
1698#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001699 }
1700
Hai Shalomfdcde762020-04-02 11:19:20 -07001701 wpa_auth_set_eapol(wpa_auth, sm->addr, WPA_EAPOL_inc_EapolFramesTx, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001702 wpa_auth_send_eapol(wpa_auth, sm->addr, (u8 *) hdr, len,
Kai Shie75b0652020-11-24 20:31:29 -08001703 sm->pairwise_set);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001704 os_free(hdr);
1705}
1706
1707
1708static void wpa_send_eapol(struct wpa_authenticator *wpa_auth,
1709 struct wpa_state_machine *sm, int key_info,
1710 const u8 *key_rsc, const u8 *nonce,
1711 const u8 *kde, size_t kde_len,
1712 int keyidx, int encr)
1713{
1714 int timeout_ms;
1715 int pairwise = key_info & WPA_KEY_INFO_KEY_TYPE;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001716 u32 ctr;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001717
Hai Shalomfdcde762020-04-02 11:19:20 -07001718 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001719 return;
1720
1721 __wpa_send_eapol(wpa_auth, sm, key_info, key_rsc, nonce, kde, kde_len,
1722 keyidx, encr, 0);
1723
1724 ctr = pairwise ? sm->TimeoutCtr : sm->GTimeoutCtr;
1725 if (ctr == 1 && wpa_auth->conf.tx_status)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001726 timeout_ms = pairwise ? eapol_key_timeout_first :
1727 eapol_key_timeout_first_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001728 else
1729 timeout_ms = eapol_key_timeout_subseq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001730 if (wpa_auth->conf.wpa_disable_eapol_key_retries &&
1731 (!pairwise || (key_info & WPA_KEY_INFO_MIC)))
1732 timeout_ms = eapol_key_timeout_no_retrans;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001733 if (pairwise && ctr == 1 && !(key_info & WPA_KEY_INFO_MIC))
1734 sm->pending_1_of_4_timeout = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08001735#ifdef TEST_FUZZ
1736 timeout_ms = 1;
1737#endif /* TEST_FUZZ */
Kai Shie75b0652020-11-24 20:31:29 -08001738#ifdef CONFIG_TESTING_OPTIONS
1739 if(wpa_auth->conf.enable_eapol_large_timeout) {
1740 timeout_ms = 50 * 1000;
1741 }
1742#endif
Hai Shalomfdcde762020-04-02 11:19:20 -07001743 wpa_printf(MSG_DEBUG,
1744 "WPA: Use EAPOL-Key timeout of %u ms (retry counter %u)",
1745 timeout_ms, ctr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001746 eloop_register_timeout(timeout_ms / 1000, (timeout_ms % 1000) * 1000,
1747 wpa_send_eapol_timeout, wpa_auth, sm);
1748}
1749
1750
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001751static int wpa_verify_key_mic(int akmp, size_t pmk_len, struct wpa_ptk *PTK,
1752 u8 *data, size_t data_len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001753{
1754 struct ieee802_1x_hdr *hdr;
1755 struct wpa_eapol_key *key;
1756 u16 key_info;
1757 int ret = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001758 u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN], *mic_pos;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001759 size_t mic_len = wpa_mic_len(akmp, pmk_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001760
1761 if (data_len < sizeof(*hdr) + sizeof(*key))
1762 return -1;
1763
1764 hdr = (struct ieee802_1x_hdr *) data;
1765 key = (struct wpa_eapol_key *) (hdr + 1);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001766 mic_pos = (u8 *) (key + 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001767 key_info = WPA_GET_BE16(key->key_info);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001768 os_memcpy(mic, mic_pos, mic_len);
1769 os_memset(mic_pos, 0, mic_len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001770 if (wpa_eapol_key_mic(PTK->kck, PTK->kck_len, akmp,
1771 key_info & WPA_KEY_INFO_TYPE_MASK,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001772 data, data_len, mic_pos) ||
1773 os_memcmp_const(mic, mic_pos, mic_len) != 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001774 ret = -1;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001775 os_memcpy(mic_pos, mic, mic_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001776 return ret;
1777}
1778
1779
1780void wpa_remove_ptk(struct wpa_state_machine *sm)
1781{
Hai Shalome21d4e82020-04-29 16:34:06 -07001782 sm->PTK_valid = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001783 os_memset(&sm->PTK, 0, sizeof(sm->PTK));
Hai Shalom60840252021-02-19 19:02:11 -08001784
1785 wpa_auth_remove_ptksa(sm->wpa_auth, sm->addr, sm->pairwise);
1786
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001787 if (wpa_auth_set_key(sm->wpa_auth, 0, WPA_ALG_NONE, sm->addr, 0, NULL,
Hai Shalomfdcde762020-04-02 11:19:20 -07001788 0, KEY_FLAG_PAIRWISE))
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001789 wpa_printf(MSG_DEBUG,
1790 "RSN: PTK removal from the driver failed");
Hai Shalomfdcde762020-04-02 11:19:20 -07001791 if (sm->use_ext_key_id &&
1792 wpa_auth_set_key(sm->wpa_auth, 0, WPA_ALG_NONE, sm->addr, 1, NULL,
1793 0, KEY_FLAG_PAIRWISE))
1794 wpa_printf(MSG_DEBUG,
1795 "RSN: PTK Key ID 1 removal from the driver failed");
Hai Shalome21d4e82020-04-29 16:34:06 -07001796 sm->pairwise_set = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001797 eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm);
1798}
1799
1800
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001801int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001802{
1803 int remove_ptk = 1;
1804
Hai Shalomfdcde762020-04-02 11:19:20 -07001805 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001806 return -1;
1807
1808 wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
1809 "event %d notification", event);
1810
1811 switch (event) {
1812 case WPA_AUTH:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001813#ifdef CONFIG_MESH
1814 /* PTKs are derived through AMPE */
1815 if (wpa_auth_start_ampe(sm->wpa_auth, sm->addr)) {
1816 /* not mesh */
1817 break;
1818 }
1819 return 0;
1820#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001821 case WPA_ASSOC:
1822 break;
1823 case WPA_DEAUTH:
1824 case WPA_DISASSOC:
Hai Shalome21d4e82020-04-29 16:34:06 -07001825 sm->DeauthenticationRequest = true;
Hai Shalom1dc4d202019-04-29 16:22:27 -07001826#ifdef CONFIG_IEEE80211R_AP
1827 os_memset(sm->PMK, 0, sizeof(sm->PMK));
1828 sm->pmk_len = 0;
1829 os_memset(sm->xxkey, 0, sizeof(sm->xxkey));
1830 sm->xxkey_len = 0;
Hai Shalom81f62d82019-07-22 12:10:00 -07001831 os_memset(sm->pmk_r1, 0, sizeof(sm->pmk_r1));
1832 sm->pmk_r1_len = 0;
Hai Shalom1dc4d202019-04-29 16:22:27 -07001833#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001834 break;
1835 case WPA_REAUTH:
1836 case WPA_REAUTH_EAPOL:
1837 if (!sm->started) {
1838 /*
1839 * When using WPS, we may end up here if the STA
1840 * manages to re-associate without the previous STA
1841 * entry getting removed. Consequently, we need to make
1842 * sure that the WPA state machines gets initialized
1843 * properly at this point.
1844 */
Hai Shalomfdcde762020-04-02 11:19:20 -07001845 wpa_printf(MSG_DEBUG,
1846 "WPA state machine had not been started - initialize now");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001847 sm->started = 1;
Hai Shalome21d4e82020-04-29 16:34:06 -07001848 sm->Init = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001849 if (wpa_sm_step(sm) == 1)
1850 return 1; /* should not really happen */
Hai Shalome21d4e82020-04-29 16:34:06 -07001851 sm->Init = false;
1852 sm->AuthenticationRequest = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001853 break;
1854 }
Hai Shalomfdcde762020-04-02 11:19:20 -07001855
1856 if (!sm->use_ext_key_id &&
1857 sm->wpa_auth->conf.wpa_deny_ptk0_rekey) {
1858 wpa_printf(MSG_INFO,
1859 "WPA: PTK0 rekey not allowed, disconnect "
1860 MACSTR, MAC2STR(sm->addr));
Hai Shalome21d4e82020-04-29 16:34:06 -07001861 sm->Disconnect = true;
Hai Shalomfdcde762020-04-02 11:19:20 -07001862 /* Try to encourage the STA to reconnect */
1863 sm->disconnect_reason =
1864 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA;
1865 break;
1866 }
1867
1868 if (sm->use_ext_key_id)
1869 sm->keyidx_active ^= 1; /* flip Key ID */
1870
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001871 if (sm->GUpdateStationKeys) {
1872 /*
1873 * Reauthentication cancels the pending group key
1874 * update for this STA.
1875 */
1876 sm->group->GKeyDoneStations--;
Hai Shalome21d4e82020-04-29 16:34:06 -07001877 sm->GUpdateStationKeys = false;
1878 sm->PtkGroupInit = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001879 }
Hai Shalome21d4e82020-04-29 16:34:06 -07001880 sm->ReAuthenticationRequest = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001881 break;
1882 case WPA_ASSOC_FT:
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001883#ifdef CONFIG_IEEE80211R_AP
Hai Shalomfdcde762020-04-02 11:19:20 -07001884 wpa_printf(MSG_DEBUG,
1885 "FT: Retry PTK configuration after association");
Hai Shalomb755a2a2020-04-23 21:49:02 -07001886 wpa_ft_install_ptk(sm, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001887
1888 /* Using FT protocol, not WPA auth state machine */
1889 sm->ft_completed = 1;
Hai Shalom81f62d82019-07-22 12:10:00 -07001890 wpa_auth_set_ptk_rekey_timer(sm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001891 return 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001892#else /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001893 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001894#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001895 case WPA_ASSOC_FILS:
1896#ifdef CONFIG_FILS
1897 wpa_printf(MSG_DEBUG,
1898 "FILS: TK configuration after association");
1899 fils_set_tk(sm);
1900 sm->fils_completed = 1;
1901 return 0;
1902#else /* CONFIG_FILS */
1903 break;
1904#endif /* CONFIG_FILS */
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02001905 case WPA_DRV_STA_REMOVED:
Hai Shalome21d4e82020-04-29 16:34:06 -07001906 sm->tk_already_set = false;
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02001907 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001908 }
1909
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001910#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001911 sm->ft_completed = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001912#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001913
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001914 if (sm->mgmt_frame_prot && event == WPA_AUTH)
1915 remove_ptk = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001916#ifdef CONFIG_FILS
1917 if (wpa_key_mgmt_fils(sm->wpa_key_mgmt) &&
1918 (event == WPA_AUTH || event == WPA_ASSOC))
1919 remove_ptk = 0;
1920#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001921
1922 if (remove_ptk) {
Hai Shalome21d4e82020-04-29 16:34:06 -07001923 sm->PTK_valid = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001924 os_memset(&sm->PTK, 0, sizeof(sm->PTK));
1925
1926 if (event != WPA_REAUTH_EAPOL)
1927 wpa_remove_ptk(sm);
1928 }
1929
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001930 if (sm->in_step_loop) {
1931 /*
1932 * wpa_sm_step() is already running - avoid recursive call to
1933 * it by making the existing loop process the new update.
1934 */
Hai Shalome21d4e82020-04-29 16:34:06 -07001935 sm->changed = true;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001936 return 0;
1937 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001938 return wpa_sm_step(sm);
1939}
1940
1941
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001942SM_STATE(WPA_PTK, INITIALIZE)
1943{
1944 SM_ENTRY_MA(WPA_PTK, INITIALIZE, wpa_ptk);
1945 if (sm->Init) {
1946 /* Init flag is not cleared here, so avoid busy
1947 * loop by claiming nothing changed. */
Hai Shalome21d4e82020-04-29 16:34:06 -07001948 sm->changed = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001949 }
1950
1951 sm->keycount = 0;
1952 if (sm->GUpdateStationKeys)
1953 sm->group->GKeyDoneStations--;
Hai Shalome21d4e82020-04-29 16:34:06 -07001954 sm->GUpdateStationKeys = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001955 if (sm->wpa == WPA_VERSION_WPA)
Hai Shalome21d4e82020-04-29 16:34:06 -07001956 sm->PInitAKeys = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001957 if (1 /* Unicast cipher supported AND (ESS OR ((IBSS or WDS) and
1958 * Local AA > Remote AA)) */) {
Hai Shalome21d4e82020-04-29 16:34:06 -07001959 sm->Pair = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001960 }
1961 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 0);
1962 wpa_remove_ptk(sm);
1963 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid, 0);
1964 sm->TimeoutCtr = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001965 if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
1966 sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP ||
1967 sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001968 wpa_auth_set_eapol(sm->wpa_auth, sm->addr,
1969 WPA_EAPOL_authorized, 0);
1970 }
1971}
1972
1973
1974SM_STATE(WPA_PTK, DISCONNECT)
1975{
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001976 u16 reason = sm->disconnect_reason;
1977
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001978 SM_ENTRY_MA(WPA_PTK, DISCONNECT, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07001979 sm->Disconnect = false;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001980 sm->disconnect_reason = 0;
1981 if (!reason)
1982 reason = WLAN_REASON_PREV_AUTH_NOT_VALID;
1983 wpa_sta_disconnect(sm->wpa_auth, sm->addr, reason);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001984}
1985
1986
1987SM_STATE(WPA_PTK, DISCONNECTED)
1988{
1989 SM_ENTRY_MA(WPA_PTK, DISCONNECTED, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07001990 sm->DeauthenticationRequest = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001991}
1992
1993
1994SM_STATE(WPA_PTK, AUTHENTICATION)
1995{
1996 SM_ENTRY_MA(WPA_PTK, AUTHENTICATION, wpa_ptk);
1997 os_memset(&sm->PTK, 0, sizeof(sm->PTK));
Hai Shalome21d4e82020-04-29 16:34:06 -07001998 sm->PTK_valid = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001999 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portControl_Auto,
2000 1);
2001 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 1);
Hai Shalome21d4e82020-04-29 16:34:06 -07002002 sm->AuthenticationRequest = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002003}
2004
2005
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002006static void wpa_group_ensure_init(struct wpa_authenticator *wpa_auth,
2007 struct wpa_group *group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002008{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002009 if (group->first_sta_seen)
2010 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002011 /*
2012 * System has run bit further than at the time hostapd was started
2013 * potentially very early during boot up. This provides better chances
2014 * of collecting more randomness on embedded systems. Re-initialize the
2015 * GMK and Counter here to improve their strength if there was not
2016 * enough entropy available immediately after system startup.
2017 */
Hai Shalomfdcde762020-04-02 11:19:20 -07002018 wpa_printf(MSG_DEBUG,
2019 "WPA: Re-initialize GMK/Counter on first station");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002020 if (random_pool_ready() != 1) {
Hai Shalomfdcde762020-04-02 11:19:20 -07002021 wpa_printf(MSG_INFO,
2022 "WPA: Not enough entropy in random pool to proceed - reject first 4-way handshake");
Hai Shalome21d4e82020-04-29 16:34:06 -07002023 group->reject_4way_hs_for_entropy = true;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002024 } else {
Hai Shalome21d4e82020-04-29 16:34:06 -07002025 group->first_sta_seen = true;
2026 group->reject_4way_hs_for_entropy = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002027 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002028
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002029 if (wpa_group_init_gmk_and_counter(wpa_auth, group) < 0 ||
2030 wpa_gtk_update(wpa_auth, group) < 0 ||
2031 wpa_group_config_group_keys(wpa_auth, group) < 0) {
2032 wpa_printf(MSG_INFO, "WPA: GMK/GTK setup failed");
Hai Shalome21d4e82020-04-29 16:34:06 -07002033 group->first_sta_seen = false;
2034 group->reject_4way_hs_for_entropy = true;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002035 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002036}
2037
2038
2039SM_STATE(WPA_PTK, AUTHENTICATION2)
2040{
2041 SM_ENTRY_MA(WPA_PTK, AUTHENTICATION2, wpa_ptk);
2042
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002043 wpa_group_ensure_init(sm->wpa_auth, sm->group);
Hai Shalome21d4e82020-04-29 16:34:06 -07002044 sm->ReAuthenticationRequest = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002045
Dmitry Shmidt04949592012-07-19 12:16:46 -07002046 /*
2047 * Definition of ANonce selection in IEEE Std 802.11i-2004 is somewhat
2048 * ambiguous. The Authenticator state machine uses a counter that is
2049 * incremented by one for each 4-way handshake. However, the security
2050 * analysis of 4-way handshake points out that unpredictable nonces
2051 * help in preventing precomputation attacks. Instead of the state
2052 * machine definition, use an unpredictable nonce value here to provide
2053 * stronger protection against potential precomputation attacks.
2054 */
2055 if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) {
Hai Shalomfdcde762020-04-02 11:19:20 -07002056 wpa_printf(MSG_ERROR,
2057 "WPA: Failed to get random data for ANonce.");
Hai Shalome21d4e82020-04-29 16:34:06 -07002058 sm->Disconnect = true;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002059 return;
2060 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002061 wpa_hexdump(MSG_DEBUG, "WPA: Assign ANonce", sm->ANonce,
2062 WPA_NONCE_LEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002063 /* IEEE 802.11i does not clear TimeoutCtr here, but this is more
2064 * logical place than INITIALIZE since AUTHENTICATION2 can be
2065 * re-entered on ReAuthenticationRequest without going through
2066 * INITIALIZE. */
2067 sm->TimeoutCtr = 0;
2068}
2069
2070
Jouni Malinen1420a892017-10-01 12:32:57 +03002071static int wpa_auth_sm_ptk_update(struct wpa_state_machine *sm)
2072{
2073 if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) {
2074 wpa_printf(MSG_ERROR,
2075 "WPA: Failed to get random data for ANonce");
Hai Shalome21d4e82020-04-29 16:34:06 -07002076 sm->Disconnect = true;
Jouni Malinen1420a892017-10-01 12:32:57 +03002077 return -1;
2078 }
2079 wpa_hexdump(MSG_DEBUG, "WPA: Assign new ANonce", sm->ANonce,
2080 WPA_NONCE_LEN);
2081 sm->TimeoutCtr = 0;
2082 return 0;
2083}
2084
2085
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002086SM_STATE(WPA_PTK, INITPMK)
2087{
2088 u8 msk[2 * PMK_LEN];
2089 size_t len = 2 * PMK_LEN;
2090
2091 SM_ENTRY_MA(WPA_PTK, INITPMK, wpa_ptk);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002092#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002093 sm->xxkey_len = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002094#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002095 if (sm->pmksa) {
2096 wpa_printf(MSG_DEBUG, "WPA: PMK from PMKSA cache");
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002097 os_memcpy(sm->PMK, sm->pmksa->pmk, sm->pmksa->pmk_len);
2098 sm->pmk_len = sm->pmksa->pmk_len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002099#ifdef CONFIG_DPP
2100 } else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP) {
2101 wpa_printf(MSG_DEBUG,
2102 "DPP: No PMKSA cache entry for STA - reject connection");
Hai Shalome21d4e82020-04-29 16:34:06 -07002103 sm->Disconnect = true;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002104 sm->disconnect_reason = WLAN_REASON_INVALID_PMKID;
2105 return;
2106#endif /* CONFIG_DPP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002107 } else if (wpa_auth_get_msk(sm->wpa_auth, sm->addr, msk, &len) == 0) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002108 unsigned int pmk_len;
2109
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002110 if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002111 pmk_len = PMK_LEN_SUITE_B_192;
2112 else
2113 pmk_len = PMK_LEN;
Hai Shalomfdcde762020-04-02 11:19:20 -07002114 wpa_printf(MSG_DEBUG,
2115 "WPA: PMK from EAPOL state machine (MSK len=%zu PMK len=%u)",
2116 len, pmk_len);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002117 if (len < pmk_len) {
2118 wpa_printf(MSG_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07002119 "WPA: MSK not long enough (%zu) to create PMK (%u)",
2120 len, pmk_len);
Hai Shalome21d4e82020-04-29 16:34:06 -07002121 sm->Disconnect = true;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002122 return;
2123 }
2124 os_memcpy(sm->PMK, msk, pmk_len);
2125 sm->pmk_len = pmk_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002126#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002127 if (len >= 2 * PMK_LEN) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002128 if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) {
2129 os_memcpy(sm->xxkey, msk, SHA384_MAC_LEN);
2130 sm->xxkey_len = SHA384_MAC_LEN;
2131 } else {
2132 os_memcpy(sm->xxkey, msk + PMK_LEN, PMK_LEN);
2133 sm->xxkey_len = PMK_LEN;
2134 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002135 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002136#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002137 } else {
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002138 wpa_printf(MSG_DEBUG, "WPA: Could not get PMK, get_msk: %p",
Paul Stewart092955c2017-02-06 09:13:09 -08002139 sm->wpa_auth->cb->get_msk);
Hai Shalome21d4e82020-04-29 16:34:06 -07002140 sm->Disconnect = true;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002141 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002142 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002143 forced_memzero(msk, sizeof(msk));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002144
2145 sm->req_replay_counter_used = 0;
Hai Shalome21d4e82020-04-29 16:34:06 -07002146 /* IEEE 802.11i does not set keyRun to false, but not doing this
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002147 * will break reauthentication since EAPOL state machines may not be
2148 * get into AUTHENTICATING state that clears keyRun before WPA state
2149 * machine enters AUTHENTICATION2 state and goes immediately to INITPMK
2150 * state and takes PMK from the previously used AAA Key. This will
2151 * eventually fail in 4-Way Handshake because Supplicant uses PMK
Hai Shalome21d4e82020-04-29 16:34:06 -07002152 * derived from the new AAA Key. Setting keyRun = false here seems to
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002153 * be good workaround for this issue. */
Hai Shalome21d4e82020-04-29 16:34:06 -07002154 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyRun, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002155}
2156
2157
2158SM_STATE(WPA_PTK, INITPSK)
2159{
2160 const u8 *psk;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002161 size_t psk_len;
2162
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002163 SM_ENTRY_MA(WPA_PTK, INITPSK, wpa_ptk);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002164 psk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr, NULL,
Hai Shalom021b0b52019-04-10 11:17:58 -07002165 &psk_len, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002166 if (psk) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002167 os_memcpy(sm->PMK, psk, psk_len);
2168 sm->pmk_len = psk_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002169#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002170 os_memcpy(sm->xxkey, psk, PMK_LEN);
2171 sm->xxkey_len = PMK_LEN;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002172#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002173 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002174#ifdef CONFIG_SAE
2175 if (wpa_auth_uses_sae(sm) && sm->pmksa) {
2176 wpa_printf(MSG_DEBUG, "SAE: PMK from PMKSA cache");
2177 os_memcpy(sm->PMK, sm->pmksa->pmk, sm->pmksa->pmk_len);
2178 sm->pmk_len = sm->pmksa->pmk_len;
Hai Shalom021b0b52019-04-10 11:17:58 -07002179#ifdef CONFIG_IEEE80211R_AP
2180 os_memcpy(sm->xxkey, sm->pmksa->pmk, sm->pmksa->pmk_len);
2181 sm->xxkey_len = sm->pmksa->pmk_len;
2182#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002183 }
2184#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002185 sm->req_replay_counter_used = 0;
2186}
2187
2188
2189SM_STATE(WPA_PTK, PTKSTART)
2190{
2191 u8 buf[2 + RSN_SELECTOR_LEN + PMKID_LEN], *pmkid = NULL;
2192 size_t pmkid_len = 0;
2193
2194 SM_ENTRY_MA(WPA_PTK, PTKSTART, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07002195 sm->PTKRequest = false;
2196 sm->TimeoutEvt = false;
2197 sm->alt_snonce_valid = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002198
2199 sm->TimeoutCtr++;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002200 if (sm->TimeoutCtr > sm->wpa_auth->conf.wpa_pairwise_update_count) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002201 /* No point in sending the EAPOL-Key - we will disconnect
2202 * immediately following this. */
2203 return;
2204 }
2205
2206 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
2207 "sending 1/4 msg of 4-Way Handshake");
2208 /*
Hai Shalomce48b4a2018-09-05 11:41:35 -07002209 * For infrastructure BSS cases, it is better for the AP not to include
2210 * the PMKID KDE in EAPOL-Key msg 1/4 since it could be used to initiate
2211 * offline search for the passphrase/PSK without having to be able to
2212 * capture a 4-way handshake from a STA that has access to the network.
2213 *
2214 * For IBSS cases, addition of PMKID KDE could be considered even with
2215 * WPA2-PSK cases that use multiple PSKs, but only if there is a single
2216 * possible PSK for this STA. However, this should not be done unless
2217 * there is support for using that information on the supplicant side.
2218 * The concern about exposing PMKID unnecessarily in infrastructure BSS
2219 * cases would also apply here, but at least in the IBSS case, this
2220 * would cover a potential real use case.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002221 */
2222 if (sm->wpa == WPA_VERSION_WPA2 &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002223 (wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) ||
2224 (sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE && sm->pmksa) ||
2225 wpa_key_mgmt_sae(sm->wpa_key_mgmt)) &&
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002226 sm->wpa_key_mgmt != WPA_KEY_MGMT_OSEN) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002227 pmkid = buf;
2228 pmkid_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN;
2229 pmkid[0] = WLAN_EID_VENDOR_SPECIFIC;
2230 pmkid[1] = RSN_SELECTOR_LEN + PMKID_LEN;
2231 RSN_SELECTOR_PUT(&pmkid[2], RSN_KEY_DATA_PMKID);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002232 if (sm->pmksa) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002233 wpa_hexdump(MSG_DEBUG,
2234 "RSN: Message 1/4 PMKID from PMKSA entry",
2235 sm->pmksa->pmkid, PMKID_LEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002236 os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN],
2237 sm->pmksa->pmkid, PMKID_LEN);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002238 } else if (wpa_key_mgmt_suite_b(sm->wpa_key_mgmt)) {
2239 /* No KCK available to derive PMKID */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002240 wpa_printf(MSG_DEBUG,
2241 "RSN: No KCK available to derive PMKID for message 1/4");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002242 pmkid = NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -07002243#ifdef CONFIG_FILS
2244 } else if (wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
2245 if (sm->pmkid_set) {
2246 wpa_hexdump(MSG_DEBUG,
2247 "RSN: Message 1/4 PMKID from FILS/ERP",
2248 sm->pmkid, PMKID_LEN);
2249 os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN],
2250 sm->pmkid, PMKID_LEN);
2251 } else {
2252 /* No PMKID available */
2253 wpa_printf(MSG_DEBUG,
2254 "RSN: No FILS/ERP PMKID available for message 1/4");
2255 pmkid = NULL;
2256 }
2257#endif /* CONFIG_FILS */
2258#ifdef CONFIG_IEEE80211R_AP
2259 } else if (wpa_key_mgmt_ft(sm->wpa_key_mgmt) &&
2260 sm->ft_completed) {
2261 wpa_printf(MSG_DEBUG,
2262 "FT: No PMKID in message 1/4 when using FT protocol");
2263 pmkid = NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -07002264#endif /* CONFIG_IEEE80211R_AP */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002265#ifdef CONFIG_SAE
2266 } else if (wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
2267 if (sm->pmkid_set) {
2268 wpa_hexdump(MSG_DEBUG,
2269 "RSN: Message 1/4 PMKID from SAE",
2270 sm->pmkid, PMKID_LEN);
2271 os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN],
2272 sm->pmkid, PMKID_LEN);
2273 } else {
2274 /* No PMKID available */
2275 wpa_printf(MSG_DEBUG,
2276 "RSN: No SAE PMKID available for message 1/4");
2277 pmkid = NULL;
2278 }
2279#endif /* CONFIG_SAE */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002280 } else {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002281 /*
2282 * Calculate PMKID since no PMKSA cache entry was
2283 * available with pre-calculated PMKID.
2284 */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002285 rsn_pmkid(sm->PMK, sm->pmk_len, sm->wpa_auth->addr,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002286 sm->addr, &pmkid[2 + RSN_SELECTOR_LEN],
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002287 sm->wpa_key_mgmt);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002288 wpa_hexdump(MSG_DEBUG,
2289 "RSN: Message 1/4 PMKID derived from PMK",
2290 &pmkid[2 + RSN_SELECTOR_LEN], PMKID_LEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002291 }
2292 }
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002293 if (!pmkid)
2294 pmkid_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002295 wpa_send_eapol(sm->wpa_auth, sm,
2296 WPA_KEY_INFO_ACK | WPA_KEY_INFO_KEY_TYPE, NULL,
2297 sm->ANonce, pmkid, pmkid_len, 0, 0);
2298}
2299
2300
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002301static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002302 const u8 *pmk, unsigned int pmk_len,
Hai Shalomfdcde762020-04-02 11:19:20 -07002303 struct wpa_ptk *ptk, int force_sha256)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002304{
Hai Shalom021b0b52019-04-10 11:17:58 -07002305 const u8 *z = NULL;
Hai Shalom60840252021-02-19 19:02:11 -08002306 size_t z_len = 0, kdk_len;
Hai Shalomfdcde762020-04-02 11:19:20 -07002307 int akmp;
Hai Shalom021b0b52019-04-10 11:17:58 -07002308
Hai Shalom60840252021-02-19 19:02:11 -08002309 if (sm->wpa_auth->conf.force_kdk_derivation ||
2310 (sm->wpa_auth->conf.secure_ltf &&
Hai Shaloma20dcd72022-02-04 13:43:00 -08002311 ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
Hai Shalom60840252021-02-19 19:02:11 -08002312 kdk_len = WPA_KDK_MAX_LEN;
2313 else
2314 kdk_len = 0;
2315
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002316#ifdef CONFIG_IEEE80211R_AP
Hai Shalom81f62d82019-07-22 12:10:00 -07002317 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
2318 if (sm->ft_completed) {
2319 u8 ptk_name[WPA_PMK_NAME_LEN];
2320
2321 return wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->pmk_r1_len,
2322 sm->SNonce, sm->ANonce,
2323 sm->addr, sm->wpa_auth->addr,
2324 sm->pmk_r1_name,
2325 ptk, ptk_name,
2326 sm->wpa_key_mgmt,
Hai Shalom60840252021-02-19 19:02:11 -08002327 sm->pairwise,
2328 kdk_len);
Hai Shalom81f62d82019-07-22 12:10:00 -07002329 }
2330 return wpa_auth_derive_ptk_ft(sm, ptk);
2331 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002332#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002333
Hai Shalom021b0b52019-04-10 11:17:58 -07002334#ifdef CONFIG_DPP2
2335 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP && sm->dpp_z) {
2336 z = wpabuf_head(sm->dpp_z);
2337 z_len = wpabuf_len(sm->dpp_z);
2338 }
2339#endif /* CONFIG_DPP2 */
2340
Hai Shalomfdcde762020-04-02 11:19:20 -07002341 akmp = sm->wpa_key_mgmt;
2342 if (force_sha256)
2343 akmp |= WPA_KEY_MGMT_PSK_SHA256;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002344 return wpa_pmk_to_ptk(pmk, pmk_len, "Pairwise key expansion",
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002345 sm->wpa_auth->addr, sm->addr, sm->ANonce, snonce,
Hai Shalom60840252021-02-19 19:02:11 -08002346 ptk, akmp, sm->pairwise, z, z_len, kdk_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002347}
2348
2349
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002350#ifdef CONFIG_FILS
2351
2352int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002353 size_t pmk_len, const u8 *snonce, const u8 *anonce,
2354 const u8 *dhss, size_t dhss_len,
2355 struct wpabuf *g_sta, struct wpabuf *g_ap)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002356{
2357 u8 ick[FILS_ICK_MAX_LEN];
2358 size_t ick_len;
2359 int res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002360 u8 fils_ft[FILS_FT_MAX_LEN];
Hai Shalom60840252021-02-19 19:02:11 -08002361 size_t fils_ft_len = 0, kdk_len;
2362
2363 if (sm->wpa_auth->conf.force_kdk_derivation ||
2364 (sm->wpa_auth->conf.secure_ltf &&
Hai Shaloma20dcd72022-02-04 13:43:00 -08002365 ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
Hai Shalom60840252021-02-19 19:02:11 -08002366 kdk_len = WPA_KDK_MAX_LEN;
2367 else
2368 kdk_len = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002369
2370 res = fils_pmk_to_ptk(pmk, pmk_len, sm->addr, sm->wpa_auth->addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002371 snonce, anonce, dhss, dhss_len,
2372 &sm->PTK, ick, &ick_len,
2373 sm->wpa_key_mgmt, sm->pairwise,
Hai Shalom60840252021-02-19 19:02:11 -08002374 fils_ft, &fils_ft_len, kdk_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002375 if (res < 0)
2376 return res;
Hai Shalome21d4e82020-04-29 16:34:06 -07002377 sm->PTK_valid = true;
2378 sm->tk_already_set = false;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002379
2380#ifdef CONFIG_IEEE80211R_AP
2381 if (fils_ft_len) {
2382 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
2383 struct wpa_auth_config *conf = &wpa_auth->conf;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002384 u8 pmk_r0[PMK_LEN_MAX], pmk_r0_name[WPA_PMK_NAME_LEN];
2385 int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002386
2387 if (wpa_derive_pmk_r0(fils_ft, fils_ft_len,
2388 conf->ssid, conf->ssid_len,
2389 conf->mobility_domain,
2390 conf->r0_key_holder,
2391 conf->r0_key_holder_len,
Roshan Pius3a1667e2018-07-03 15:17:14 -07002392 sm->addr, pmk_r0, pmk_r0_name,
2393 use_sha384) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002394 return -1;
2395
Roshan Pius3a1667e2018-07-03 15:17:14 -07002396 wpa_ft_store_pmk_fils(sm, pmk_r0, pmk_r0_name);
Hai Shalom81f62d82019-07-22 12:10:00 -07002397 forced_memzero(fils_ft, sizeof(fils_ft));
Hai Shalom021b0b52019-04-10 11:17:58 -07002398
2399 res = wpa_derive_pmk_r1_name(pmk_r0_name, conf->r1_key_holder,
2400 sm->addr, sm->pmk_r1_name,
2401 use_sha384);
Hai Shalom81f62d82019-07-22 12:10:00 -07002402 forced_memzero(pmk_r0, PMK_LEN_MAX);
Hai Shalom021b0b52019-04-10 11:17:58 -07002403 if (res < 0)
2404 return -1;
2405 wpa_hexdump(MSG_DEBUG, "FILS+FT: PMKR1Name", sm->pmk_r1_name,
2406 WPA_PMK_NAME_LEN);
2407 sm->pmk_r1_name_valid = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002408 }
2409#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002410
2411 res = fils_key_auth_sk(ick, ick_len, snonce, anonce,
2412 sm->addr, sm->wpa_auth->addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002413 g_sta ? wpabuf_head(g_sta) : NULL,
2414 g_sta ? wpabuf_len(g_sta) : 0,
2415 g_ap ? wpabuf_head(g_ap) : NULL,
2416 g_ap ? wpabuf_len(g_ap) : 0,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002417 sm->wpa_key_mgmt, sm->fils_key_auth_sta,
2418 sm->fils_key_auth_ap,
2419 &sm->fils_key_auth_len);
Hai Shalom81f62d82019-07-22 12:10:00 -07002420 forced_memzero(ick, sizeof(ick));
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002421
2422 /* Store nonces for (Re)Association Request/Response frame processing */
2423 os_memcpy(sm->SNonce, snonce, FILS_NONCE_LEN);
2424 os_memcpy(sm->ANonce, anonce, FILS_NONCE_LEN);
2425
2426 return res;
2427}
2428
2429
2430static int wpa_aead_decrypt(struct wpa_state_machine *sm, struct wpa_ptk *ptk,
2431 u8 *buf, size_t buf_len, u16 *_key_data_len)
2432{
2433 struct ieee802_1x_hdr *hdr;
2434 struct wpa_eapol_key *key;
2435 u8 *pos;
2436 u16 key_data_len;
2437 u8 *tmp;
2438 const u8 *aad[1];
2439 size_t aad_len[1];
2440
2441 hdr = (struct ieee802_1x_hdr *) buf;
2442 key = (struct wpa_eapol_key *) (hdr + 1);
2443 pos = (u8 *) (key + 1);
2444 key_data_len = WPA_GET_BE16(pos);
2445 if (key_data_len < AES_BLOCK_SIZE ||
2446 key_data_len > buf_len - sizeof(*hdr) - sizeof(*key) - 2) {
2447 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO,
2448 "No room for AES-SIV data in the frame");
2449 return -1;
2450 }
2451 pos += 2; /* Pointing at the Encrypted Key Data field */
2452
2453 tmp = os_malloc(key_data_len);
2454 if (!tmp)
2455 return -1;
2456
2457 /* AES-SIV AAD from EAPOL protocol version field (inclusive) to
2458 * to Key Data (exclusive). */
2459 aad[0] = buf;
2460 aad_len[0] = pos - buf;
2461 if (aes_siv_decrypt(ptk->kek, ptk->kek_len, pos, key_data_len,
2462 1, aad, aad_len, tmp) < 0) {
2463 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO,
2464 "Invalid AES-SIV data in the frame");
2465 bin_clear_free(tmp, key_data_len);
2466 return -1;
2467 }
2468
2469 /* AEAD decryption and validation completed successfully */
2470 key_data_len -= AES_BLOCK_SIZE;
2471 wpa_hexdump_key(MSG_DEBUG, "WPA: Decrypted Key Data",
2472 tmp, key_data_len);
2473
2474 /* Replace Key Data field with the decrypted version */
2475 os_memcpy(pos, tmp, key_data_len);
2476 pos -= 2; /* Key Data Length field */
2477 WPA_PUT_BE16(pos, key_data_len);
2478 bin_clear_free(tmp, key_data_len);
2479 if (_key_data_len)
2480 *_key_data_len = key_data_len;
2481 return 0;
2482}
2483
2484
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002485const u8 * wpa_fils_validate_fils_session(struct wpa_state_machine *sm,
2486 const u8 *ies, size_t ies_len,
2487 const u8 *fils_session)
2488{
2489 const u8 *ie, *end;
2490 const u8 *session = NULL;
2491
2492 if (!wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
2493 wpa_printf(MSG_DEBUG,
2494 "FILS: Not a FILS AKM - reject association");
2495 return NULL;
2496 }
2497
2498 /* Verify Session element */
2499 ie = ies;
2500 end = ((const u8 *) ie) + ies_len;
2501 while (ie + 1 < end) {
2502 if (ie + 2 + ie[1] > end)
2503 break;
2504 if (ie[0] == WLAN_EID_EXTENSION &&
2505 ie[1] >= 1 + FILS_SESSION_LEN &&
2506 ie[2] == WLAN_EID_EXT_FILS_SESSION) {
2507 session = ie;
2508 break;
2509 }
2510 ie += 2 + ie[1];
2511 }
2512
2513 if (!session) {
2514 wpa_printf(MSG_DEBUG,
2515 "FILS: %s: Could not find FILS Session element in Assoc Req - reject",
2516 __func__);
2517 return NULL;
2518 }
2519
2520 if (!fils_session) {
2521 wpa_printf(MSG_DEBUG,
2522 "FILS: %s: Could not find FILS Session element in STA entry - reject",
2523 __func__);
2524 return NULL;
2525 }
2526
2527 if (os_memcmp(fils_session, session + 3, FILS_SESSION_LEN) != 0) {
2528 wpa_printf(MSG_DEBUG, "FILS: Session mismatch");
2529 wpa_hexdump(MSG_DEBUG, "FILS: Expected FILS Session",
2530 fils_session, FILS_SESSION_LEN);
2531 wpa_hexdump(MSG_DEBUG, "FILS: Received FILS Session",
2532 session + 3, FILS_SESSION_LEN);
2533 return NULL;
2534 }
2535 return session;
2536}
2537
2538
2539int wpa_fils_validate_key_confirm(struct wpa_state_machine *sm, const u8 *ies,
2540 size_t ies_len)
2541{
2542 struct ieee802_11_elems elems;
2543
2544 if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed) {
2545 wpa_printf(MSG_DEBUG,
2546 "FILS: Failed to parse decrypted elements");
2547 return -1;
2548 }
2549
2550 if (!elems.fils_session) {
2551 wpa_printf(MSG_DEBUG, "FILS: No FILS Session element");
2552 return -1;
2553 }
2554
2555 if (!elems.fils_key_confirm) {
2556 wpa_printf(MSG_DEBUG, "FILS: No FILS Key Confirm element");
2557 return -1;
2558 }
2559
2560 if (elems.fils_key_confirm_len != sm->fils_key_auth_len) {
2561 wpa_printf(MSG_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07002562 "FILS: Unexpected Key-Auth length %d (expected %zu)",
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002563 elems.fils_key_confirm_len,
Hai Shalomfdcde762020-04-02 11:19:20 -07002564 sm->fils_key_auth_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002565 return -1;
2566 }
2567
2568 if (os_memcmp(elems.fils_key_confirm, sm->fils_key_auth_sta,
2569 sm->fils_key_auth_len) != 0) {
2570 wpa_printf(MSG_DEBUG, "FILS: Key-Auth mismatch");
2571 wpa_hexdump(MSG_DEBUG, "FILS: Received Key-Auth",
2572 elems.fils_key_confirm, elems.fils_key_confirm_len);
2573 wpa_hexdump(MSG_DEBUG, "FILS: Expected Key-Auth",
2574 sm->fils_key_auth_sta, sm->fils_key_auth_len);
2575 return -1;
2576 }
2577
2578 return 0;
2579}
2580
2581
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002582int fils_decrypt_assoc(struct wpa_state_machine *sm, const u8 *fils_session,
2583 const struct ieee80211_mgmt *mgmt, size_t frame_len,
2584 u8 *pos, size_t left)
2585{
2586 u16 fc, stype;
2587 const u8 *end, *ie_start, *ie, *session, *crypt;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002588 const u8 *aad[5];
2589 size_t aad_len[5];
2590
2591 if (!sm || !sm->PTK_valid) {
2592 wpa_printf(MSG_DEBUG,
2593 "FILS: No KEK to decrypt Assocication Request frame");
2594 return -1;
2595 }
2596
2597 if (!wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
2598 wpa_printf(MSG_DEBUG,
2599 "FILS: Not a FILS AKM - reject association");
2600 return -1;
2601 }
2602
2603 end = ((const u8 *) mgmt) + frame_len;
2604 fc = le_to_host16(mgmt->frame_control);
2605 stype = WLAN_FC_GET_STYPE(fc);
2606 if (stype == WLAN_FC_STYPE_REASSOC_REQ)
2607 ie_start = mgmt->u.reassoc_req.variable;
2608 else
2609 ie_start = mgmt->u.assoc_req.variable;
2610 ie = ie_start;
2611
2612 /*
2613 * Find FILS Session element which is the last unencrypted element in
2614 * the frame.
2615 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002616 session = wpa_fils_validate_fils_session(sm, ie, end - ie,
2617 fils_session);
2618 if (!session) {
2619 wpa_printf(MSG_DEBUG, "FILS: Session validation failed");
2620 return -1;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002621 }
2622
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002623 crypt = session + 2 + session[1];
2624
2625 if (end - crypt < AES_BLOCK_SIZE) {
2626 wpa_printf(MSG_DEBUG,
2627 "FILS: Too short frame to include AES-SIV data");
2628 return -1;
2629 }
2630
2631 /* AES-SIV AAD vectors */
2632
2633 /* The STA's MAC address */
2634 aad[0] = mgmt->sa;
2635 aad_len[0] = ETH_ALEN;
2636 /* The AP's BSSID */
2637 aad[1] = mgmt->da;
2638 aad_len[1] = ETH_ALEN;
2639 /* The STA's nonce */
2640 aad[2] = sm->SNonce;
2641 aad_len[2] = FILS_NONCE_LEN;
2642 /* The AP's nonce */
2643 aad[3] = sm->ANonce;
2644 aad_len[3] = FILS_NONCE_LEN;
2645 /*
2646 * The (Re)Association Request frame from the Capability Information
2647 * field to the FILS Session element (both inclusive).
2648 */
2649 aad[4] = (const u8 *) &mgmt->u.assoc_req.capab_info;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002650 aad_len[4] = crypt - aad[4];
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002651
2652 if (aes_siv_decrypt(sm->PTK.kek, sm->PTK.kek_len, crypt, end - crypt,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002653 5, aad, aad_len, pos + (crypt - ie_start)) < 0) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002654 wpa_printf(MSG_DEBUG,
2655 "FILS: Invalid AES-SIV data in the frame");
2656 return -1;
2657 }
2658 wpa_hexdump(MSG_DEBUG, "FILS: Decrypted Association Request elements",
2659 pos, left - AES_BLOCK_SIZE);
2660
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002661 if (wpa_fils_validate_key_confirm(sm, pos, left - AES_BLOCK_SIZE) < 0) {
2662 wpa_printf(MSG_DEBUG, "FILS: Key Confirm validation failed");
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002663 return -1;
2664 }
2665
2666 return left - AES_BLOCK_SIZE;
2667}
2668
2669
2670int fils_encrypt_assoc(struct wpa_state_machine *sm, u8 *buf,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002671 size_t current_len, size_t max_len,
2672 const struct wpabuf *hlp)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002673{
2674 u8 *end = buf + max_len;
2675 u8 *pos = buf + current_len;
2676 struct ieee80211_mgmt *mgmt;
2677 struct wpabuf *plain;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002678 const u8 *aad[5];
2679 size_t aad_len[5];
2680
2681 if (!sm || !sm->PTK_valid)
2682 return -1;
2683
2684 wpa_hexdump(MSG_DEBUG,
2685 "FILS: Association Response frame before FILS processing",
2686 buf, current_len);
2687
2688 mgmt = (struct ieee80211_mgmt *) buf;
2689
2690 /* AES-SIV AAD vectors */
2691
2692 /* The AP's BSSID */
2693 aad[0] = mgmt->sa;
2694 aad_len[0] = ETH_ALEN;
2695 /* The STA's MAC address */
2696 aad[1] = mgmt->da;
2697 aad_len[1] = ETH_ALEN;
2698 /* The AP's nonce */
2699 aad[2] = sm->ANonce;
2700 aad_len[2] = FILS_NONCE_LEN;
2701 /* The STA's nonce */
2702 aad[3] = sm->SNonce;
2703 aad_len[3] = FILS_NONCE_LEN;
2704 /*
2705 * The (Re)Association Response frame from the Capability Information
2706 * field (the same offset in both Association and Reassociation
2707 * Response frames) to the FILS Session element (both inclusive).
2708 */
2709 aad[4] = (const u8 *) &mgmt->u.assoc_resp.capab_info;
2710 aad_len[4] = pos - aad[4];
2711
2712 /* The following elements will be encrypted with AES-SIV */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002713 plain = fils_prepare_plainbuf(sm, hlp);
2714 if (!plain) {
2715 wpa_printf(MSG_DEBUG, "FILS: Plain buffer prep failed");
2716 return -1;
2717 }
2718
2719 if (pos + wpabuf_len(plain) + AES_BLOCK_SIZE > end) {
2720 wpa_printf(MSG_DEBUG,
2721 "FILS: Not enough room for FILS elements");
Hai Shalom81f62d82019-07-22 12:10:00 -07002722 wpabuf_clear_free(plain);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002723 return -1;
2724 }
2725
2726 wpa_hexdump_buf_key(MSG_DEBUG, "FILS: Association Response plaintext",
2727 plain);
2728
2729 if (aes_siv_encrypt(sm->PTK.kek, sm->PTK.kek_len,
2730 wpabuf_head(plain), wpabuf_len(plain),
2731 5, aad, aad_len, pos) < 0) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002732 wpabuf_clear_free(plain);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002733 return -1;
2734 }
2735
2736 wpa_hexdump(MSG_DEBUG,
2737 "FILS: Encrypted Association Response elements",
2738 pos, AES_BLOCK_SIZE + wpabuf_len(plain));
2739 current_len += wpabuf_len(plain) + AES_BLOCK_SIZE;
Hai Shalom81f62d82019-07-22 12:10:00 -07002740 wpabuf_clear_free(plain);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002741
2742 sm->fils_completed = 1;
2743
2744 return current_len;
2745}
2746
2747
2748static struct wpabuf * fils_prepare_plainbuf(struct wpa_state_machine *sm,
2749 const struct wpabuf *hlp)
2750{
2751 struct wpabuf *plain;
2752 u8 *len, *tmp, *tmp2;
2753 u8 hdr[2];
Hai Shaloma20dcd72022-02-04 13:43:00 -08002754 u8 *gtk, stub_gtk[32];
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002755 size_t gtk_len;
2756 struct wpa_group *gsm;
Hai Shalomfdcde762020-04-02 11:19:20 -07002757 size_t plain_len;
2758 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002759
Hai Shalomfdcde762020-04-02 11:19:20 -07002760 plain_len = 1000 + ieee80211w_kde_len(sm);
2761 if (conf->transition_disable)
2762 plain_len += 2 + RSN_SELECTOR_LEN + 1;
2763 plain = wpabuf_alloc(plain_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002764 if (!plain)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002765 return NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002766
2767 /* TODO: FILS Public Key */
2768
2769 /* FILS Key Confirmation */
2770 wpabuf_put_u8(plain, WLAN_EID_EXTENSION); /* Element ID */
2771 wpabuf_put_u8(plain, 1 + sm->fils_key_auth_len); /* Length */
2772 /* Element ID Extension */
2773 wpabuf_put_u8(plain, WLAN_EID_EXT_FILS_KEY_CONFIRM);
2774 wpabuf_put_data(plain, sm->fils_key_auth_ap, sm->fils_key_auth_len);
2775
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002776 /* FILS HLP Container */
2777 if (hlp)
2778 wpabuf_put_buf(plain, hlp);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002779
2780 /* TODO: FILS IP Address Assignment */
2781
2782 /* Key Delivery */
2783 gsm = sm->group;
2784 wpabuf_put_u8(plain, WLAN_EID_EXTENSION); /* Element ID */
2785 len = wpabuf_put(plain, 1);
2786 wpabuf_put_u8(plain, WLAN_EID_EXT_KEY_DELIVERY);
2787 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN,
2788 wpabuf_put(plain, WPA_KEY_RSC_LEN));
2789 /* GTK KDE */
2790 gtk = gsm->GTK[gsm->GN - 1];
2791 gtk_len = gsm->GTK_len;
Hai Shalomfdcde762020-04-02 11:19:20 -07002792 if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002793 /*
2794 * Provide unique random GTK to each STA to prevent use
2795 * of GTK in the BSS.
2796 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08002797 if (random_get_bytes(stub_gtk, gtk_len) < 0) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002798 wpabuf_clear_free(plain);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002799 return NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002800 }
Hai Shaloma20dcd72022-02-04 13:43:00 -08002801 gtk = stub_gtk;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002802 }
2803 hdr[0] = gsm->GN & 0x03;
2804 hdr[1] = 0;
2805 tmp = wpabuf_put(plain, 0);
2806 tmp2 = wpa_add_kde(tmp, RSN_KEY_DATA_GROUPKEY, hdr, 2,
2807 gtk, gtk_len);
2808 wpabuf_put(plain, tmp2 - tmp);
2809
Hai Shalomfdcde762020-04-02 11:19:20 -07002810 /* IGTK KDE and BIGTK KDE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002811 tmp = wpabuf_put(plain, 0);
2812 tmp2 = ieee80211w_kde_add(sm, tmp);
2813 wpabuf_put(plain, tmp2 - tmp);
2814
Hai Shalomfdcde762020-04-02 11:19:20 -07002815 if (conf->transition_disable) {
2816 tmp = wpabuf_put(plain, 0);
2817 tmp2 = wpa_add_kde(tmp, WFA_KEY_DATA_TRANSITION_DISABLE,
2818 &conf->transition_disable, 1, NULL, 0);
2819 wpabuf_put(plain, tmp2 - tmp);
2820 }
2821
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002822 *len = (u8 *) wpabuf_put(plain, 0) - len - 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08002823
2824#ifdef CONFIG_OCV
2825 if (wpa_auth_uses_ocv(sm)) {
2826 struct wpa_channel_info ci;
2827 u8 *pos;
2828
2829 if (wpa_channel_info(sm->wpa_auth, &ci) != 0) {
2830 wpa_printf(MSG_WARNING,
2831 "FILS: Failed to get channel info for OCI element");
Hai Shalom81f62d82019-07-22 12:10:00 -07002832 wpabuf_clear_free(plain);
Hai Shalom74f70d42019-02-11 14:42:39 -08002833 return NULL;
2834 }
Hai Shalom899fcc72020-10-19 14:38:18 -07002835#ifdef CONFIG_TESTING_OPTIONS
2836 if (conf->oci_freq_override_fils_assoc) {
2837 wpa_printf(MSG_INFO,
2838 "TEST: Override OCI frequency %d -> %u MHz",
2839 ci.frequency,
2840 conf->oci_freq_override_fils_assoc);
2841 ci.frequency = conf->oci_freq_override_fils_assoc;
2842 }
2843#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom74f70d42019-02-11 14:42:39 -08002844
2845 pos = wpabuf_put(plain, OCV_OCI_EXTENDED_LEN);
2846 if (ocv_insert_extended_oci(&ci, pos) < 0) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002847 wpabuf_clear_free(plain);
Hai Shalom74f70d42019-02-11 14:42:39 -08002848 return NULL;
2849 }
2850 }
2851#endif /* CONFIG_OCV */
2852
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002853 return plain;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002854}
2855
2856
2857int fils_set_tk(struct wpa_state_machine *sm)
2858{
2859 enum wpa_alg alg;
2860 int klen;
2861
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002862 if (!sm || !sm->PTK_valid) {
2863 wpa_printf(MSG_DEBUG, "FILS: No valid PTK available to set TK");
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002864 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002865 }
2866 if (sm->tk_already_set) {
2867 wpa_printf(MSG_DEBUG, "FILS: TK already set to the driver");
2868 return -1;
2869 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002870
2871 alg = wpa_cipher_to_alg(sm->pairwise);
2872 klen = wpa_cipher_key_len(sm->pairwise);
2873
2874 wpa_printf(MSG_DEBUG, "FILS: Configure TK to the driver");
2875 if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0,
Hai Shalomfdcde762020-04-02 11:19:20 -07002876 sm->PTK.tk, klen, KEY_FLAG_PAIRWISE_RX_TX)) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002877 wpa_printf(MSG_DEBUG, "FILS: Failed to set TK to the driver");
2878 return -1;
2879 }
Hai Shalome21d4e82020-04-29 16:34:06 -07002880 sm->tk_already_set = true;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002881
Hai Shalom60840252021-02-19 19:02:11 -08002882 wpa_auth_store_ptksa(sm->wpa_auth, sm->addr, sm->pairwise,
2883 dot11RSNAConfigPMKLifetime, &sm->PTK);
2884
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002885 return 0;
2886}
2887
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002888
2889u8 * hostapd_eid_assoc_fils_session(struct wpa_state_machine *sm, u8 *buf,
2890 const u8 *fils_session, struct wpabuf *hlp)
2891{
2892 struct wpabuf *plain;
2893 u8 *pos = buf;
2894
2895 /* FILS Session */
2896 *pos++ = WLAN_EID_EXTENSION; /* Element ID */
2897 *pos++ = 1 + FILS_SESSION_LEN; /* Length */
2898 *pos++ = WLAN_EID_EXT_FILS_SESSION; /* Element ID Extension */
2899 os_memcpy(pos, fils_session, FILS_SESSION_LEN);
2900 pos += FILS_SESSION_LEN;
2901
2902 plain = fils_prepare_plainbuf(sm, hlp);
2903 if (!plain) {
2904 wpa_printf(MSG_DEBUG, "FILS: Plain buffer prep failed");
2905 return NULL;
2906 }
2907
2908 os_memcpy(pos, wpabuf_head(plain), wpabuf_len(plain));
2909 pos += wpabuf_len(plain);
2910
Hai Shalomfdcde762020-04-02 11:19:20 -07002911 wpa_printf(MSG_DEBUG, "%s: plain buf_len: %zu", __func__,
2912 wpabuf_len(plain));
Hai Shalom81f62d82019-07-22 12:10:00 -07002913 wpabuf_clear_free(plain);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002914 sm->fils_completed = 1;
2915 return pos;
2916}
2917
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002918#endif /* CONFIG_FILS */
2919
2920
Hai Shalom74f70d42019-02-11 14:42:39 -08002921#ifdef CONFIG_OCV
2922int get_sta_tx_parameters(struct wpa_state_machine *sm, int ap_max_chanwidth,
2923 int ap_seg1_idx, int *bandwidth, int *seg1_idx)
2924{
2925 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
2926
2927 if (!wpa_auth->cb->get_sta_tx_params)
2928 return -1;
2929 return wpa_auth->cb->get_sta_tx_params(wpa_auth->cb_ctx, sm->addr,
2930 ap_max_chanwidth, ap_seg1_idx,
2931 bandwidth, seg1_idx);
2932}
2933#endif /* CONFIG_OCV */
2934
2935
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002936SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
2937{
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002938 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002939 struct wpa_ptk PTK;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07002940 int ok = 0, psk_found = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002941 const u8 *pmk = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002942 size_t pmk_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002943 int ft;
2944 const u8 *eapol_key_ie, *key_data, *mic;
2945 u16 key_data_length;
2946 size_t mic_len, eapol_key_ie_len;
2947 struct ieee802_1x_hdr *hdr;
2948 struct wpa_eapol_key *key;
2949 struct wpa_eapol_ie_parse kde;
Hai Shalom021b0b52019-04-10 11:17:58 -07002950 int vlan_id = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002951 int owe_ptk_workaround = !!wpa_auth->conf.owe_ptk_workaround;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002952
2953 SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07002954 sm->EAPOLKeyReceived = false;
2955 sm->update_snonce = false;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002956 os_memset(&PTK, 0, sizeof(PTK));
2957
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002958 mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002959
2960 /* WPA with IEEE 802.1X: use the derived PMK from EAP
2961 * WPA-PSK: iterate through possible PSKs and select the one matching
2962 * the packet */
2963 for (;;) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002964 if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
2965 !wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002966 pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr,
Hai Shalom021b0b52019-04-10 11:17:58 -07002967 sm->p2p_dev_addr, pmk, &pmk_len,
2968 &vlan_id);
Hai Shalomfdcde762020-04-02 11:19:20 -07002969 if (!pmk)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002970 break;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07002971 psk_found = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002972#ifdef CONFIG_IEEE80211R_AP
2973 if (wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) {
2974 os_memcpy(sm->xxkey, pmk, pmk_len);
2975 sm->xxkey_len = pmk_len;
2976 }
2977#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002978 } else {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002979 pmk = sm->PMK;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002980 pmk_len = sm->pmk_len;
2981 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002982
Hai Shalom81f62d82019-07-22 12:10:00 -07002983 if ((!pmk || !pmk_len) && sm->pmksa) {
2984 wpa_printf(MSG_DEBUG, "WPA: Use PMK from PMKSA cache");
2985 pmk = sm->pmksa->pmk;
2986 pmk_len = sm->pmksa->pmk_len;
2987 }
2988
Hai Shalomfdcde762020-04-02 11:19:20 -07002989 if (wpa_derive_ptk(sm, sm->SNonce, pmk, pmk_len, &PTK,
2990 owe_ptk_workaround == 2) < 0)
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002991 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002992
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002993 if (mic_len &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002994 wpa_verify_key_mic(sm->wpa_key_mgmt, pmk_len, &PTK,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002995 sm->last_rx_eapol_key,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002996 sm->last_rx_eapol_key_len) == 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07002997 if (sm->PMK != pmk) {
2998 os_memcpy(sm->PMK, pmk, pmk_len);
2999 sm->pmk_len = pmk_len;
3000 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003001 ok = 1;
3002 break;
3003 }
3004
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003005#ifdef CONFIG_FILS
3006 if (!mic_len &&
3007 wpa_aead_decrypt(sm, &PTK, sm->last_rx_eapol_key,
3008 sm->last_rx_eapol_key_len, NULL) == 0) {
3009 ok = 1;
3010 break;
3011 }
3012#endif /* CONFIG_FILS */
3013
Hai Shalomfdcde762020-04-02 11:19:20 -07003014#ifdef CONFIG_OWE
3015 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE && pmk_len > 32 &&
3016 owe_ptk_workaround == 1) {
3017 wpa_printf(MSG_DEBUG,
3018 "OWE: Try PTK derivation workaround with SHA256");
3019 owe_ptk_workaround = 2;
3020 continue;
3021 }
3022#endif /* CONFIG_OWE */
3023
Roshan Pius3a1667e2018-07-03 15:17:14 -07003024 if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
3025 wpa_key_mgmt_sae(sm->wpa_key_mgmt))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003026 break;
3027 }
3028
3029 if (!ok) {
3030 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
3031 "invalid MIC in msg 2/4 of 4-Way Handshake");
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07003032 if (psk_found)
3033 wpa_auth_psk_failure_report(sm->wpa_auth, sm->addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003034 return;
3035 }
3036
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003037 /*
3038 * Note: last_rx_eapol_key length fields have already been validated in
3039 * wpa_receive().
3040 */
3041 hdr = (struct ieee802_1x_hdr *) sm->last_rx_eapol_key;
3042 key = (struct wpa_eapol_key *) (hdr + 1);
3043 mic = (u8 *) (key + 1);
3044 key_data = mic + mic_len + 2;
3045 key_data_length = WPA_GET_BE16(mic + mic_len);
3046 if (key_data_length > sm->last_rx_eapol_key_len - sizeof(*hdr) -
3047 sizeof(*key) - mic_len - 2)
3048 return;
3049
3050 if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) {
3051 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
3052 "received EAPOL-Key msg 2/4 with invalid Key Data contents");
3053 return;
3054 }
3055 if (kde.rsn_ie) {
3056 eapol_key_ie = kde.rsn_ie;
3057 eapol_key_ie_len = kde.rsn_ie_len;
3058 } else if (kde.osen) {
3059 eapol_key_ie = kde.osen;
3060 eapol_key_ie_len = kde.osen_len;
3061 } else {
3062 eapol_key_ie = kde.wpa_ie;
3063 eapol_key_ie_len = kde.wpa_ie_len;
3064 }
3065 ft = sm->wpa == WPA_VERSION_WPA2 && wpa_key_mgmt_ft(sm->wpa_key_mgmt);
Hai Shalomfdcde762020-04-02 11:19:20 -07003066 if (!sm->wpa_ie ||
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003067 wpa_compare_rsn_ie(ft, sm->wpa_ie, sm->wpa_ie_len,
3068 eapol_key_ie, eapol_key_ie_len)) {
3069 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
3070 "WPA IE from (Re)AssocReq did not match with msg 2/4");
3071 if (sm->wpa_ie) {
3072 wpa_hexdump(MSG_DEBUG, "WPA IE in AssocReq",
3073 sm->wpa_ie, sm->wpa_ie_len);
3074 }
3075 wpa_hexdump(MSG_DEBUG, "WPA IE in msg 2/4",
3076 eapol_key_ie, eapol_key_ie_len);
3077 /* MLME-DEAUTHENTICATE.request */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003078 wpa_sta_disconnect(wpa_auth, sm->addr,
3079 WLAN_REASON_PREV_AUTH_NOT_VALID);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003080 return;
3081 }
Hai Shalomc3565922019-10-28 11:58:20 -07003082 if ((!sm->rsnxe && kde.rsnxe) ||
3083 (sm->rsnxe && !kde.rsnxe) ||
3084 (sm->rsnxe && kde.rsnxe &&
3085 (sm->rsnxe_len != kde.rsnxe_len ||
3086 os_memcmp(sm->rsnxe, kde.rsnxe, sm->rsnxe_len) != 0))) {
3087 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
3088 "RSNXE from (Re)AssocReq did not match the one in EAPOL-Key msg 2/4");
3089 wpa_hexdump(MSG_DEBUG, "RSNXE in AssocReq",
3090 sm->rsnxe, sm->rsnxe_len);
3091 wpa_hexdump(MSG_DEBUG, "RSNXE in EAPOL-Key msg 2/4",
3092 kde.rsnxe, kde.rsnxe_len);
3093 /* MLME-DEAUTHENTICATE.request */
3094 wpa_sta_disconnect(wpa_auth, sm->addr,
3095 WLAN_REASON_PREV_AUTH_NOT_VALID);
3096 return;
3097 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003098#ifdef CONFIG_OCV
3099 if (wpa_auth_uses_ocv(sm)) {
3100 struct wpa_channel_info ci;
3101 int tx_chanwidth;
3102 int tx_seg1_idx;
Hai Shalom899fcc72020-10-19 14:38:18 -07003103 enum oci_verify_result res;
Hai Shalom74f70d42019-02-11 14:42:39 -08003104
3105 if (wpa_channel_info(wpa_auth, &ci) != 0) {
3106 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
3107 "Failed to get channel info to validate received OCI in EAPOL-Key 2/4");
3108 return;
3109 }
3110
3111 if (get_sta_tx_parameters(sm,
3112 channel_width_to_int(ci.chanwidth),
3113 ci.seg1_idx, &tx_chanwidth,
3114 &tx_seg1_idx) < 0)
3115 return;
3116
Hai Shalom899fcc72020-10-19 14:38:18 -07003117 res = ocv_verify_tx_params(kde.oci, kde.oci_len, &ci,
3118 tx_chanwidth, tx_seg1_idx);
3119 if (wpa_auth_uses_ocv(sm) == 2 && res == OCI_NOT_FOUND) {
3120 /* Work around misbehaving STAs */
3121 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
3122 "Disable OCV with a STA that does not send OCI");
3123 wpa_auth_set_ocv(sm, 0);
3124 } else if (res != OCI_SUCCESS) {
3125 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
3126 "OCV failed: %s", ocv_errorstr);
3127 if (wpa_auth->conf.msg_ctx)
3128 wpa_msg(wpa_auth->conf.msg_ctx, MSG_INFO,
3129 OCV_FAILURE "addr=" MACSTR
3130 " frame=eapol-key-m2 error=%s",
3131 MAC2STR(sm->addr), ocv_errorstr);
Hai Shalom74f70d42019-02-11 14:42:39 -08003132 return;
3133 }
3134 }
3135#endif /* CONFIG_OCV */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003136#ifdef CONFIG_IEEE80211R_AP
3137 if (ft && ft_check_msg_2_of_4(wpa_auth, sm, &kde) < 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003138 wpa_sta_disconnect(wpa_auth, sm->addr,
3139 WLAN_REASON_PREV_AUTH_NOT_VALID);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003140 return;
3141 }
3142#endif /* CONFIG_IEEE80211R_AP */
3143#ifdef CONFIG_P2P
3144 if (kde.ip_addr_req && kde.ip_addr_req[0] &&
3145 wpa_auth->ip_pool && WPA_GET_BE32(sm->ip_addr) == 0) {
3146 int idx;
3147 wpa_printf(MSG_DEBUG,
3148 "P2P: IP address requested in EAPOL-Key exchange");
3149 idx = bitfield_get_first_zero(wpa_auth->ip_pool);
3150 if (idx >= 0) {
3151 u32 start = WPA_GET_BE32(wpa_auth->conf.ip_addr_start);
3152 bitfield_set(wpa_auth->ip_pool, idx);
3153 WPA_PUT_BE32(sm->ip_addr, start + idx);
3154 wpa_printf(MSG_DEBUG,
3155 "P2P: Assigned IP address %u.%u.%u.%u to "
3156 MACSTR, sm->ip_addr[0], sm->ip_addr[1],
3157 sm->ip_addr[2], sm->ip_addr[3],
3158 MAC2STR(sm->addr));
3159 }
3160 }
3161#endif /* CONFIG_P2P */
3162
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003163#ifdef CONFIG_DPP2
3164 if (DPP_VERSION > 1 && kde.dpp_kde) {
3165 wpa_printf(MSG_DEBUG,
3166 "DPP: peer Protocol Version %u Flags 0x%x",
3167 kde.dpp_kde[0], kde.dpp_kde[1]);
3168 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP &&
3169 wpa_auth->conf.dpp_pfs != 2 &&
3170 (kde.dpp_kde[1] & DPP_KDE_PFS_ALLOWED) &&
3171 !sm->dpp_z) {
3172 wpa_printf(MSG_INFO,
3173 "DPP: Peer indicated it supports PFS and local configuration allows this, but PFS was not negotiated for the association");
3174 wpa_sta_disconnect(wpa_auth, sm->addr,
3175 WLAN_REASON_PREV_AUTH_NOT_VALID);
3176 return;
3177 }
3178 }
3179#endif /* CONFIG_DPP2 */
3180
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003181#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003182 if (sm->wpa == WPA_VERSION_WPA2 && wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
3183 /*
3184 * Verify that PMKR1Name from EAPOL-Key message 2/4 matches
3185 * with the value we derived.
3186 */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003187 if (os_memcmp_const(sm->sup_pmk_r1_name, sm->pmk_r1_name,
3188 WPA_PMK_NAME_LEN) != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003189 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07003190 "PMKR1Name mismatch in FT 4-way handshake");
3191 wpa_hexdump(MSG_DEBUG,
3192 "FT: PMKR1Name from Supplicant",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003193 sm->sup_pmk_r1_name, WPA_PMK_NAME_LEN);
3194 wpa_hexdump(MSG_DEBUG, "FT: Derived PMKR1Name",
3195 sm->pmk_r1_name, WPA_PMK_NAME_LEN);
3196 return;
3197 }
3198 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003199#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003200
Hai Shalom021b0b52019-04-10 11:17:58 -07003201 if (vlan_id && wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
3202 wpa_auth_update_vlan(wpa_auth, sm->addr, vlan_id) < 0) {
3203 wpa_sta_disconnect(wpa_auth, sm->addr,
3204 WLAN_REASON_PREV_AUTH_NOT_VALID);
3205 return;
3206 }
3207
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003208 sm->pending_1_of_4_timeout = 0;
3209 eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm);
3210
Hai Shalom60840252021-02-19 19:02:11 -08003211 if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) && sm->PMK != pmk) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003212 /* PSK may have changed from the previous choice, so update
3213 * state machine data based on whatever PSK was selected here.
3214 */
3215 os_memcpy(sm->PMK, pmk, PMK_LEN);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003216 sm->pmk_len = PMK_LEN;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003217 }
3218
Hai Shalome21d4e82020-04-29 16:34:06 -07003219 sm->MICVerified = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003220
3221 os_memcpy(&sm->PTK, &PTK, sizeof(PTK));
Hai Shalom81f62d82019-07-22 12:10:00 -07003222 forced_memzero(&PTK, sizeof(PTK));
Hai Shalome21d4e82020-04-29 16:34:06 -07003223 sm->PTK_valid = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003224}
3225
3226
3227SM_STATE(WPA_PTK, PTKCALCNEGOTIATING2)
3228{
3229 SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING2, wpa_ptk);
3230 sm->TimeoutCtr = 0;
3231}
3232
3233
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003234static int ieee80211w_kde_len(struct wpa_state_machine *sm)
3235{
Hai Shalomfdcde762020-04-02 11:19:20 -07003236 size_t len = 0;
3237
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003238 if (sm->mgmt_frame_prot) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003239 len += 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN;
3240 len += wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
3241 }
3242 if (sm->mgmt_frame_prot && sm->wpa_auth->conf.beacon_prot) {
3243 len += 2 + RSN_SELECTOR_LEN + WPA_BIGTK_KDE_PREFIX_LEN;
3244 len += wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003245 }
3246
Hai Shalomfdcde762020-04-02 11:19:20 -07003247 return len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003248}
3249
3250
3251static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos)
3252{
3253 struct wpa_igtk_kde igtk;
Hai Shalomfdcde762020-04-02 11:19:20 -07003254 struct wpa_bigtk_kde bigtk;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003255 struct wpa_group *gsm = sm->group;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003256 u8 rsc[WPA_KEY_RSC_LEN];
Hai Shalomfdcde762020-04-02 11:19:20 -07003257 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
3258 size_t len = wpa_cipher_key_len(conf->group_mgmt_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003259
3260 if (!sm->mgmt_frame_prot)
3261 return pos;
3262
3263 igtk.keyid[0] = gsm->GN_igtk;
3264 igtk.keyid[1] = 0;
3265 if (gsm->wpa_group_state != WPA_GROUP_SETKEYSDONE ||
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003266 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, rsc) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003267 os_memset(igtk.pn, 0, sizeof(igtk.pn));
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003268 else
3269 os_memcpy(igtk.pn, rsc, sizeof(igtk.pn));
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003270 os_memcpy(igtk.igtk, gsm->IGTK[gsm->GN_igtk - 4], len);
Hai Shalomfdcde762020-04-02 11:19:20 -07003271 if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003272 /*
3273 * Provide unique random IGTK to each STA to prevent use of
3274 * IGTK in the BSS.
3275 */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003276 if (random_get_bytes(igtk.igtk, len) < 0)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003277 return pos;
3278 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003279 pos = wpa_add_kde(pos, RSN_KEY_DATA_IGTK,
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003280 (const u8 *) &igtk, WPA_IGTK_KDE_PREFIX_LEN + len,
3281 NULL, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003282
Hai Shalomfdcde762020-04-02 11:19:20 -07003283 if (!conf->beacon_prot)
3284 return pos;
3285
3286 bigtk.keyid[0] = gsm->GN_bigtk;
3287 bigtk.keyid[1] = 0;
3288 if (gsm->wpa_group_state != WPA_GROUP_SETKEYSDONE ||
3289 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_bigtk, rsc) < 0)
3290 os_memset(bigtk.pn, 0, sizeof(bigtk.pn));
3291 else
3292 os_memcpy(bigtk.pn, rsc, sizeof(bigtk.pn));
3293 os_memcpy(bigtk.bigtk, gsm->BIGTK[gsm->GN_bigtk - 6], len);
Hai Shalom899fcc72020-10-19 14:38:18 -07003294 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
3295 /*
3296 * Provide unique random BIGTK to each OSEN STA to prevent use
3297 * of BIGTK in the BSS.
3298 */
3299 if (random_get_bytes(bigtk.bigtk, len) < 0)
3300 return pos;
3301 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003302 pos = wpa_add_kde(pos, RSN_KEY_DATA_BIGTK,
3303 (const u8 *) &bigtk, WPA_BIGTK_KDE_PREFIX_LEN + len,
3304 NULL, 0);
3305
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003306 return pos;
3307}
3308
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003309
Hai Shalom74f70d42019-02-11 14:42:39 -08003310static int ocv_oci_len(struct wpa_state_machine *sm)
3311{
3312#ifdef CONFIG_OCV
3313 if (wpa_auth_uses_ocv(sm))
3314 return OCV_OCI_KDE_LEN;
3315#endif /* CONFIG_OCV */
3316 return 0;
3317}
3318
Hai Shalom899fcc72020-10-19 14:38:18 -07003319
3320static int ocv_oci_add(struct wpa_state_machine *sm, u8 **argpos,
3321 unsigned int freq)
Hai Shalom74f70d42019-02-11 14:42:39 -08003322{
3323#ifdef CONFIG_OCV
3324 struct wpa_channel_info ci;
3325
3326 if (!wpa_auth_uses_ocv(sm))
3327 return 0;
3328
3329 if (wpa_channel_info(sm->wpa_auth, &ci) != 0) {
3330 wpa_printf(MSG_WARNING,
3331 "Failed to get channel info for OCI element");
3332 return -1;
3333 }
Hai Shalom899fcc72020-10-19 14:38:18 -07003334#ifdef CONFIG_TESTING_OPTIONS
3335 if (freq) {
3336 wpa_printf(MSG_INFO,
3337 "TEST: Override OCI KDE frequency %d -> %u MHz",
3338 ci.frequency, freq);
3339 ci.frequency = freq;
3340 }
3341#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom74f70d42019-02-11 14:42:39 -08003342
3343 return ocv_insert_oci_kde(&ci, argpos);
3344#else /* CONFIG_OCV */
3345 return 0;
3346#endif /* CONFIG_OCV */
3347}
3348
3349
Hai Shalomfdcde762020-04-02 11:19:20 -07003350#ifdef CONFIG_TESTING_OPTIONS
3351static u8 * replace_ie(const char *name, const u8 *old_buf, size_t *len, u8 eid,
3352 const u8 *ie, size_t ie_len)
3353{
3354 const u8 *elem;
3355 u8 *buf;
3356
3357 wpa_printf(MSG_DEBUG, "TESTING: %s EAPOL override", name);
3358 wpa_hexdump(MSG_DEBUG, "TESTING: wpa_ie before override",
3359 old_buf, *len);
3360 buf = os_malloc(*len + ie_len);
3361 if (!buf)
3362 return NULL;
3363 os_memcpy(buf, old_buf, *len);
3364 elem = get_ie(buf, *len, eid);
3365 if (elem) {
3366 u8 elem_len = 2 + elem[1];
3367
3368 os_memmove((void *) elem, elem + elem_len,
3369 *len - (elem - buf) - elem_len);
3370 *len -= elem_len;
3371 }
3372 os_memcpy(buf + *len, ie, ie_len);
3373 *len += ie_len;
3374 wpa_hexdump(MSG_DEBUG, "TESTING: wpa_ie after EAPOL override",
3375 buf, *len);
3376
3377 return buf;
3378}
3379#endif /* CONFIG_TESTING_OPTIONS */
3380
3381
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003382SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
3383{
Hai Shaloma20dcd72022-02-04 13:43:00 -08003384 u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde = NULL, *pos, stub_gtk[32];
Hai Shalomfdcde762020-04-02 11:19:20 -07003385 size_t gtk_len, kde_len, wpa_ie_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003386 struct wpa_group *gsm = sm->group;
3387 u8 *wpa_ie;
Hai Shalomfdcde762020-04-02 11:19:20 -07003388 int secure, gtkidx, encr = 0;
3389 u8 *wpa_ie_buf = NULL, *wpa_ie_buf2 = NULL;
3390 u8 hdr[2];
3391 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003392
3393 SM_ENTRY_MA(WPA_PTK, PTKINITNEGOTIATING, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07003394 sm->TimeoutEvt = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003395
3396 sm->TimeoutCtr++;
Hai Shalomfdcde762020-04-02 11:19:20 -07003397 if (conf->wpa_disable_eapol_key_retries && sm->TimeoutCtr > 1) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003398 /* Do not allow retransmission of EAPOL-Key msg 3/4 */
3399 return;
3400 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003401 if (sm->TimeoutCtr > conf->wpa_pairwise_update_count) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003402 /* No point in sending the EAPOL-Key - we will disconnect
3403 * immediately following this. */
3404 return;
3405 }
3406
3407 /* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, [MDIE],
Hai Shalomfdcde762020-04-02 11:19:20 -07003408 GTK[GN], IGTK, [BIGTK], [FTIE], [TIE * 2])
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003409 */
3410 os_memset(rsc, 0, WPA_KEY_RSC_LEN);
3411 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc);
3412 /* If FT is used, wpa_auth->wpa_ie includes both RSNIE and MDIE */
3413 wpa_ie = sm->wpa_auth->wpa_ie;
3414 wpa_ie_len = sm->wpa_auth->wpa_ie_len;
Hai Shalomfdcde762020-04-02 11:19:20 -07003415 if (sm->wpa == WPA_VERSION_WPA && (conf->wpa & WPA_PROTO_RSN) &&
3416 wpa_ie_len > wpa_ie[1] + 2U && wpa_ie[0] == WLAN_EID_RSN) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003417 /* WPA-only STA, remove RSN IE and possible MDIE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003418 wpa_ie = wpa_ie + wpa_ie[1] + 2;
Hai Shalom60840252021-02-19 19:02:11 -08003419 if (wpa_ie[0] == WLAN_EID_RSNX)
3420 wpa_ie = wpa_ie + wpa_ie[1] + 2;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003421 if (wpa_ie[0] == WLAN_EID_MOBILITY_DOMAIN)
3422 wpa_ie = wpa_ie + wpa_ie[1] + 2;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003423 wpa_ie_len = wpa_ie[1] + 2;
3424 }
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003425#ifdef CONFIG_TESTING_OPTIONS
Hai Shalomfdcde762020-04-02 11:19:20 -07003426 if (conf->rsne_override_eapol_set) {
3427 wpa_ie_buf2 = replace_ie(
3428 "RSNE", wpa_ie, &wpa_ie_len, WLAN_EID_RSN,
3429 conf->rsne_override_eapol,
3430 conf->rsne_override_eapol_len);
3431 if (!wpa_ie_buf2)
3432 goto done;
3433 wpa_ie = wpa_ie_buf2;
3434 }
3435 if (conf->rsnxe_override_eapol_set) {
3436 wpa_ie_buf = replace_ie(
3437 "RSNXE", wpa_ie, &wpa_ie_len, WLAN_EID_RSNX,
3438 conf->rsnxe_override_eapol,
3439 conf->rsnxe_override_eapol_len);
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003440 if (!wpa_ie_buf)
Hai Shalomfdcde762020-04-02 11:19:20 -07003441 goto done;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003442 wpa_ie = wpa_ie_buf;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003443 }
3444#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003445 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
3446 "sending 3/4 msg of 4-Way Handshake");
3447 if (sm->wpa == WPA_VERSION_WPA2) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003448 if (sm->use_ext_key_id && sm->TimeoutCtr == 1 &&
3449 wpa_auth_set_key(sm->wpa_auth, 0,
3450 wpa_cipher_to_alg(sm->pairwise),
3451 sm->addr,
3452 sm->keyidx_active, sm->PTK.tk,
3453 wpa_cipher_key_len(sm->pairwise),
3454 KEY_FLAG_PAIRWISE_RX)) {
3455 wpa_sta_disconnect(sm->wpa_auth, sm->addr,
3456 WLAN_REASON_PREV_AUTH_NOT_VALID);
3457 return;
3458 }
3459
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003460 /* WPA2 send GTK in the 4-way handshake */
3461 secure = 1;
3462 gtk = gsm->GTK[gsm->GN - 1];
3463 gtk_len = gsm->GTK_len;
Hai Shalomfdcde762020-04-02 11:19:20 -07003464 if (conf->disable_gtk ||
Roshan Pius3a1667e2018-07-03 15:17:14 -07003465 sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003466 /*
3467 * Provide unique random GTK to each STA to prevent use
3468 * of GTK in the BSS.
3469 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003470 if (random_get_bytes(stub_gtk, gtk_len) < 0)
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003471 goto done;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003472 gtk = stub_gtk;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003473 }
Hai Shalomc3565922019-10-28 11:58:20 -07003474 gtkidx = gsm->GN;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003475 _rsc = rsc;
3476 encr = 1;
3477 } else {
3478 /* WPA does not include GTK in msg 3/4 */
3479 secure = 0;
3480 gtk = NULL;
3481 gtk_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003482 _rsc = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003483 if (sm->rx_eapol_key_secure) {
3484 /*
3485 * It looks like Windows 7 supplicant tries to use
3486 * Secure bit in msg 2/4 after having reported Michael
3487 * MIC failure and it then rejects the 4-way handshake
3488 * if msg 3/4 does not set Secure bit. Work around this
3489 * by setting the Secure bit here even in the case of
3490 * WPA if the supplicant used it first.
3491 */
3492 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07003493 "STA used Secure bit in WPA msg 2/4 - set Secure for 3/4 as workaround");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003494 secure = 1;
3495 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003496 }
3497
Hai Shalom74f70d42019-02-11 14:42:39 -08003498 kde_len = wpa_ie_len + ieee80211w_kde_len(sm) + ocv_oci_len(sm);
Hai Shalomfdcde762020-04-02 11:19:20 -07003499
3500 if (sm->use_ext_key_id)
3501 kde_len += 2 + RSN_SELECTOR_LEN + 2;
3502
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003503 if (gtk)
3504 kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003505#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003506 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
3507 kde_len += 2 + PMKID_LEN; /* PMKR1Name into RSN IE */
3508 kde_len += 300; /* FTIE + 2 * TIE */
3509 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003510#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08003511#ifdef CONFIG_P2P
3512 if (WPA_GET_BE32(sm->ip_addr) > 0)
3513 kde_len += 2 + RSN_SELECTOR_LEN + 3 * 4;
3514#endif /* CONFIG_P2P */
Hai Shalomfdcde762020-04-02 11:19:20 -07003515
3516 if (conf->transition_disable)
3517 kde_len += 2 + RSN_SELECTOR_LEN + 1;
3518
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003519#ifdef CONFIG_DPP2
3520 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP)
3521 kde_len += 2 + RSN_SELECTOR_LEN + 2;
3522#endif /* CONFIG_DPP2 */
3523
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003524 kde = os_malloc(kde_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07003525 if (!kde)
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003526 goto done;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003527
3528 pos = kde;
3529 os_memcpy(pos, wpa_ie, wpa_ie_len);
3530 pos += wpa_ie_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003531#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003532 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08003533 int res;
3534 size_t elen;
3535
3536 elen = pos - kde;
3537 res = wpa_insert_pmkid(kde, &elen, sm->pmk_r1_name);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003538 if (res < 0) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003539 wpa_printf(MSG_ERROR,
3540 "FT: Failed to insert PMKR1Name into RSN IE in EAPOL-Key data");
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003541 goto done;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003542 }
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08003543 pos -= wpa_ie_len;
3544 pos += elen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003545 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003546#endif /* CONFIG_IEEE80211R_AP */
Hai Shalomfdcde762020-04-02 11:19:20 -07003547 hdr[1] = 0;
3548
3549 if (sm->use_ext_key_id) {
3550 hdr[0] = sm->keyidx_active & 0x01;
3551 pos = wpa_add_kde(pos, RSN_KEY_DATA_KEYID, hdr, 2, NULL, 0);
3552 }
3553
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003554 if (gtk) {
Hai Shalomc3565922019-10-28 11:58:20 -07003555 hdr[0] = gtkidx & 0x03;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003556 pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
3557 gtk, gtk_len);
3558 }
3559 pos = ieee80211w_kde_add(sm, pos);
Hai Shalom899fcc72020-10-19 14:38:18 -07003560 if (ocv_oci_add(sm, &pos, conf->oci_freq_override_eapol_m3) < 0)
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003561 goto done;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003562
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003563#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003564 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
3565 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003566
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08003567 if (sm->assoc_resp_ftie &&
3568 kde + kde_len - pos >= 2 + sm->assoc_resp_ftie[1]) {
3569 os_memcpy(pos, sm->assoc_resp_ftie,
3570 2 + sm->assoc_resp_ftie[1]);
3571 res = 2 + sm->assoc_resp_ftie[1];
3572 } else {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003573 int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt);
3574
3575 res = wpa_write_ftie(conf, use_sha384,
3576 conf->r0_key_holder,
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08003577 conf->r0_key_holder_len,
3578 NULL, NULL, pos,
3579 kde + kde_len - pos,
Hai Shalomfdcde762020-04-02 11:19:20 -07003580 NULL, 0, 0);
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08003581 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003582 if (res < 0) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003583 wpa_printf(MSG_ERROR,
3584 "FT: Failed to insert FTIE into EAPOL-Key Key Data");
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003585 goto done;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003586 }
3587 pos += res;
3588
3589 /* TIE[ReassociationDeadline] (TU) */
3590 *pos++ = WLAN_EID_TIMEOUT_INTERVAL;
3591 *pos++ = 5;
3592 *pos++ = WLAN_TIMEOUT_REASSOC_DEADLINE;
3593 WPA_PUT_LE32(pos, conf->reassociation_deadline);
3594 pos += 4;
3595
3596 /* TIE[KeyLifetime] (seconds) */
3597 *pos++ = WLAN_EID_TIMEOUT_INTERVAL;
3598 *pos++ = 5;
3599 *pos++ = WLAN_TIMEOUT_KEY_LIFETIME;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003600 WPA_PUT_LE32(pos, conf->r0_key_lifetime);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003601 pos += 4;
3602 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003603#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08003604#ifdef CONFIG_P2P
3605 if (WPA_GET_BE32(sm->ip_addr) > 0) {
3606 u8 addr[3 * 4];
3607 os_memcpy(addr, sm->ip_addr, 4);
Hai Shalomfdcde762020-04-02 11:19:20 -07003608 os_memcpy(addr + 4, conf->ip_addr_mask, 4);
3609 os_memcpy(addr + 8, conf->ip_addr_go, 4);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08003610 pos = wpa_add_kde(pos, WFA_KEY_DATA_IP_ADDR_ALLOC,
3611 addr, sizeof(addr), NULL, 0);
3612 }
3613#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003614
Hai Shalomfdcde762020-04-02 11:19:20 -07003615 if (conf->transition_disable)
3616 pos = wpa_add_kde(pos, WFA_KEY_DATA_TRANSITION_DISABLE,
3617 &conf->transition_disable, 1, NULL, 0);
3618
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003619#ifdef CONFIG_DPP2
3620 if (DPP_VERSION > 1 && sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP) {
3621 u8 payload[2];
3622
3623 payload[0] = DPP_VERSION; /* Protocol Version */
3624 payload[1] = 0; /* Flags */
3625 if (conf->dpp_pfs == 0)
3626 payload[1] |= DPP_KDE_PFS_ALLOWED;
3627 else if (conf->dpp_pfs == 1)
3628 payload[1] |= DPP_KDE_PFS_ALLOWED |
3629 DPP_KDE_PFS_REQUIRED;
3630 pos = wpa_add_kde(pos, WFA_KEY_DATA_DPP,
3631 payload, sizeof(payload), NULL, 0);
3632 }
3633#endif /* CONFIG_DPP2 */
3634
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003635 wpa_send_eapol(sm->wpa_auth, sm,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003636 (secure ? WPA_KEY_INFO_SECURE : 0) |
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003637 (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
3638 WPA_KEY_INFO_MIC : 0) |
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003639 WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL |
3640 WPA_KEY_INFO_KEY_TYPE,
Hai Shalomc3565922019-10-28 11:58:20 -07003641 _rsc, sm->ANonce, kde, pos - kde, 0, encr);
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003642done:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003643 os_free(kde);
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003644 os_free(wpa_ie_buf);
Hai Shalomfdcde762020-04-02 11:19:20 -07003645 os_free(wpa_ie_buf2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003646}
3647
3648
3649SM_STATE(WPA_PTK, PTKINITDONE)
3650{
3651 SM_ENTRY_MA(WPA_PTK, PTKINITDONE, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07003652 sm->EAPOLKeyReceived = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003653 if (sm->Pair) {
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07003654 enum wpa_alg alg = wpa_cipher_to_alg(sm->pairwise);
3655 int klen = wpa_cipher_key_len(sm->pairwise);
Hai Shalomfdcde762020-04-02 11:19:20 -07003656 int res;
3657
3658 if (sm->use_ext_key_id)
3659 res = wpa_auth_set_key(sm->wpa_auth, 0, 0, sm->addr,
3660 sm->keyidx_active, NULL, 0,
3661 KEY_FLAG_PAIRWISE_RX_TX_MODIFY);
3662 else
3663 res = wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr,
3664 0, sm->PTK.tk, klen,
3665 KEY_FLAG_PAIRWISE_RX_TX);
3666 if (res) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003667 wpa_sta_disconnect(sm->wpa_auth, sm->addr,
3668 WLAN_REASON_PREV_AUTH_NOT_VALID);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003669 return;
3670 }
3671 /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */
Hai Shalome21d4e82020-04-29 16:34:06 -07003672 sm->pairwise_set = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003673
Hai Shalom81f62d82019-07-22 12:10:00 -07003674 wpa_auth_set_ptk_rekey_timer(sm);
Hai Shalom60840252021-02-19 19:02:11 -08003675 wpa_auth_store_ptksa(sm->wpa_auth, sm->addr, sm->pairwise,
3676 dot11RSNAConfigPMKLifetime, &sm->PTK);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003677
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003678 if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
3679 sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP ||
3680 sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003681 wpa_auth_set_eapol(sm->wpa_auth, sm->addr,
3682 WPA_EAPOL_authorized, 1);
3683 }
3684 }
3685
3686 if (0 /* IBSS == TRUE */) {
3687 sm->keycount++;
3688 if (sm->keycount == 2) {
3689 wpa_auth_set_eapol(sm->wpa_auth, sm->addr,
3690 WPA_EAPOL_portValid, 1);
3691 }
3692 } else {
3693 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid,
3694 1);
3695 }
Hai Shalome21d4e82020-04-29 16:34:06 -07003696 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyAvailable,
3697 false);
3698 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyDone, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003699 if (sm->wpa == WPA_VERSION_WPA)
Hai Shalome21d4e82020-04-29 16:34:06 -07003700 sm->PInitAKeys = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003701 else
Hai Shalome21d4e82020-04-29 16:34:06 -07003702 sm->has_GTK = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003703 wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO,
3704 "pairwise key handshake completed (%s)",
3705 sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN");
Hai Shaloma20dcd72022-02-04 13:43:00 -08003706 wpa_msg(sm->wpa_auth->conf.msg_ctx, MSG_INFO, "EAPOL-4WAY-HS-COMPLETED "
3707 MACSTR, MAC2STR(sm->addr));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003708
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003709#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003710 wpa_ft_push_pmk_r1(sm->wpa_auth, sm->addr);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003711#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003712}
3713
3714
3715SM_STEP(WPA_PTK)
3716{
3717 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
Hai Shalomfdcde762020-04-02 11:19:20 -07003718 struct wpa_auth_config *conf = &wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003719
3720 if (sm->Init)
3721 SM_ENTER(WPA_PTK, INITIALIZE);
3722 else if (sm->Disconnect
3723 /* || FIX: dot11RSNAConfigSALifetime timeout */) {
3724 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
3725 "WPA_PTK: sm->Disconnect");
3726 SM_ENTER(WPA_PTK, DISCONNECT);
3727 }
3728 else if (sm->DeauthenticationRequest)
3729 SM_ENTER(WPA_PTK, DISCONNECTED);
3730 else if (sm->AuthenticationRequest)
3731 SM_ENTER(WPA_PTK, AUTHENTICATION);
3732 else if (sm->ReAuthenticationRequest)
3733 SM_ENTER(WPA_PTK, AUTHENTICATION2);
Jouni Malinen1420a892017-10-01 12:32:57 +03003734 else if (sm->PTKRequest) {
3735 if (wpa_auth_sm_ptk_update(sm) < 0)
3736 SM_ENTER(WPA_PTK, DISCONNECTED);
3737 else
3738 SM_ENTER(WPA_PTK, PTKSTART);
3739 } else switch (sm->wpa_ptk_state) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003740 case WPA_PTK_INITIALIZE:
3741 break;
3742 case WPA_PTK_DISCONNECT:
3743 SM_ENTER(WPA_PTK, DISCONNECTED);
3744 break;
3745 case WPA_PTK_DISCONNECTED:
3746 SM_ENTER(WPA_PTK, INITIALIZE);
3747 break;
3748 case WPA_PTK_AUTHENTICATION:
3749 SM_ENTER(WPA_PTK, AUTHENTICATION2);
3750 break;
3751 case WPA_PTK_AUTHENTICATION2:
3752 if (wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) &&
Hai Shalomfdcde762020-04-02 11:19:20 -07003753 wpa_auth_get_eapol(wpa_auth, sm->addr,
Hai Shalome21d4e82020-04-29 16:34:06 -07003754 WPA_EAPOL_keyRun))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003755 SM_ENTER(WPA_PTK, INITPMK);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003756 else if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
3757 sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003758 /* FIX: && 802.1X::keyRun */)
3759 SM_ENTER(WPA_PTK, INITPSK);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003760 else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP)
3761 SM_ENTER(WPA_PTK, INITPMK);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003762 break;
3763 case WPA_PTK_INITPMK:
Hai Shalomfdcde762020-04-02 11:19:20 -07003764 if (wpa_auth_get_eapol(wpa_auth, sm->addr,
Hai Shalome21d4e82020-04-29 16:34:06 -07003765 WPA_EAPOL_keyAvailable)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003766 SM_ENTER(WPA_PTK, PTKSTART);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003767#ifdef CONFIG_DPP
3768 } else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP && sm->pmksa) {
3769 SM_ENTER(WPA_PTK, PTKSTART);
3770#endif /* CONFIG_DPP */
3771 } else {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003772 wpa_auth->dot11RSNA4WayHandshakeFailures++;
Hai Shalomfdcde762020-04-02 11:19:20 -07003773 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003774 "INITPMK - keyAvailable = false");
3775 SM_ENTER(WPA_PTK, DISCONNECT);
3776 }
3777 break;
3778 case WPA_PTK_INITPSK:
Hai Shalomfdcde762020-04-02 11:19:20 -07003779 if (wpa_auth_get_psk(wpa_auth, sm->addr, sm->p2p_dev_addr,
Hai Shalom021b0b52019-04-10 11:17:58 -07003780 NULL, NULL, NULL)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003781 SM_ENTER(WPA_PTK, PTKSTART);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003782#ifdef CONFIG_SAE
3783 } else if (wpa_auth_uses_sae(sm) && sm->pmksa) {
3784 SM_ENTER(WPA_PTK, PTKSTART);
3785#endif /* CONFIG_SAE */
3786 } else {
Hai Shalomfdcde762020-04-02 11:19:20 -07003787 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003788 "no PSK configured for the STA");
3789 wpa_auth->dot11RSNA4WayHandshakeFailures++;
3790 SM_ENTER(WPA_PTK, DISCONNECT);
3791 }
3792 break;
3793 case WPA_PTK_PTKSTART:
3794 if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest &&
3795 sm->EAPOLKeyPairwise)
3796 SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING);
Hai Shalomfdcde762020-04-02 11:19:20 -07003797 else if (sm->TimeoutCtr > conf->wpa_pairwise_update_count) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003798 wpa_auth->dot11RSNA4WayHandshakeFailures++;
Hai Shalomfdcde762020-04-02 11:19:20 -07003799 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
3800 "PTKSTART: Retry limit %u reached",
3801 conf->wpa_pairwise_update_count);
Hai Shalome21d4e82020-04-29 16:34:06 -07003802 sm->disconnect_reason =
3803 WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003804 SM_ENTER(WPA_PTK, DISCONNECT);
3805 } else if (sm->TimeoutEvt)
3806 SM_ENTER(WPA_PTK, PTKSTART);
3807 break;
3808 case WPA_PTK_PTKCALCNEGOTIATING:
3809 if (sm->MICVerified)
3810 SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING2);
3811 else if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest &&
3812 sm->EAPOLKeyPairwise)
3813 SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING);
3814 else if (sm->TimeoutEvt)
3815 SM_ENTER(WPA_PTK, PTKSTART);
3816 break;
3817 case WPA_PTK_PTKCALCNEGOTIATING2:
3818 SM_ENTER(WPA_PTK, PTKINITNEGOTIATING);
3819 break;
3820 case WPA_PTK_PTKINITNEGOTIATING:
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003821 if (sm->update_snonce)
3822 SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING);
3823 else if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest &&
3824 sm->EAPOLKeyPairwise && sm->MICVerified)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003825 SM_ENTER(WPA_PTK, PTKINITDONE);
3826 else if (sm->TimeoutCtr >
Hai Shalomfdcde762020-04-02 11:19:20 -07003827 conf->wpa_pairwise_update_count ||
3828 (conf->wpa_disable_eapol_key_retries &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003829 sm->TimeoutCtr > 1)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003830 wpa_auth->dot11RSNA4WayHandshakeFailures++;
Hai Shalomfdcde762020-04-02 11:19:20 -07003831 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
3832 "PTKINITNEGOTIATING: Retry limit %u reached",
3833 conf->wpa_pairwise_update_count);
Hai Shalome21d4e82020-04-29 16:34:06 -07003834 sm->disconnect_reason =
3835 WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003836 SM_ENTER(WPA_PTK, DISCONNECT);
3837 } else if (sm->TimeoutEvt)
3838 SM_ENTER(WPA_PTK, PTKINITNEGOTIATING);
3839 break;
3840 case WPA_PTK_PTKINITDONE:
3841 break;
3842 }
3843}
3844
3845
3846SM_STATE(WPA_PTK_GROUP, IDLE)
3847{
3848 SM_ENTRY_MA(WPA_PTK_GROUP, IDLE, wpa_ptk_group);
3849 if (sm->Init) {
3850 /* Init flag is not cleared here, so avoid busy
3851 * loop by claiming nothing changed. */
Hai Shalome21d4e82020-04-29 16:34:06 -07003852 sm->changed = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003853 }
3854 sm->GTimeoutCtr = 0;
3855}
3856
3857
3858SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING)
3859{
3860 u8 rsc[WPA_KEY_RSC_LEN];
3861 struct wpa_group *gsm = sm->group;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003862 const u8 *kde;
3863 u8 *kde_buf = NULL, *pos, hdr[2];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003864 size_t kde_len;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003865 u8 *gtk, stub_gtk[32];
Hai Shalomfdcde762020-04-02 11:19:20 -07003866 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003867
3868 SM_ENTRY_MA(WPA_PTK_GROUP, REKEYNEGOTIATING, wpa_ptk_group);
3869
3870 sm->GTimeoutCtr++;
Hai Shalomfdcde762020-04-02 11:19:20 -07003871 if (conf->wpa_disable_eapol_key_retries && sm->GTimeoutCtr > 1) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003872 /* Do not allow retransmission of EAPOL-Key group msg 1/2 */
3873 return;
3874 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003875 if (sm->GTimeoutCtr > conf->wpa_group_update_count) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003876 /* No point in sending the EAPOL-Key - we will disconnect
3877 * immediately following this. */
3878 return;
3879 }
3880
3881 if (sm->wpa == WPA_VERSION_WPA)
Hai Shalome21d4e82020-04-29 16:34:06 -07003882 sm->PInitAKeys = false;
3883 sm->TimeoutEvt = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003884 /* Send EAPOL(1, 1, 1, !Pair, G, RSC, GNonce, MIC(PTK), GTK[GN]) */
3885 os_memset(rsc, 0, WPA_KEY_RSC_LEN);
3886 if (gsm->wpa_group_state == WPA_GROUP_SETKEYSDONE)
3887 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc);
3888 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
3889 "sending 1/2 msg of Group Key Handshake");
3890
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003891 gtk = gsm->GTK[gsm->GN - 1];
Hai Shalomfdcde762020-04-02 11:19:20 -07003892 if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003893 /*
3894 * Provide unique random GTK to each STA to prevent use
3895 * of GTK in the BSS.
3896 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003897 if (random_get_bytes(stub_gtk, gsm->GTK_len) < 0)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003898 return;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003899 gtk = stub_gtk;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003900 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003901 if (sm->wpa == WPA_VERSION_WPA2) {
3902 kde_len = 2 + RSN_SELECTOR_LEN + 2 + gsm->GTK_len +
Hai Shalom74f70d42019-02-11 14:42:39 -08003903 ieee80211w_kde_len(sm) + ocv_oci_len(sm);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003904 kde_buf = os_malloc(kde_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07003905 if (!kde_buf)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003906 return;
3907
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003908 kde = pos = kde_buf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003909 hdr[0] = gsm->GN & 0x03;
3910 hdr[1] = 0;
3911 pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003912 gtk, gsm->GTK_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003913 pos = ieee80211w_kde_add(sm, pos);
Hai Shalom899fcc72020-10-19 14:38:18 -07003914 if (ocv_oci_add(sm, &pos,
3915 conf->oci_freq_override_eapol_g1) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -08003916 os_free(kde_buf);
3917 return;
3918 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003919 kde_len = pos - kde;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003920 } else {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003921 kde = gtk;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003922 kde_len = gsm->GTK_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003923 }
3924
3925 wpa_send_eapol(sm->wpa_auth, sm,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003926 WPA_KEY_INFO_SECURE |
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003927 (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
3928 WPA_KEY_INFO_MIC : 0) |
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003929 WPA_KEY_INFO_ACK |
3930 (!sm->Pair ? WPA_KEY_INFO_INSTALL : 0),
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003931 rsc, NULL, kde, kde_len, gsm->GN, 1);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003932
3933 os_free(kde_buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003934}
3935
3936
3937SM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED)
3938{
Hai Shalom74f70d42019-02-11 14:42:39 -08003939 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
Hai Shalomfdcde762020-04-02 11:19:20 -07003940#ifdef CONFIG_OCV
Hai Shalom74f70d42019-02-11 14:42:39 -08003941 const u8 *key_data, *mic;
3942 struct ieee802_1x_hdr *hdr;
3943 struct wpa_eapol_key *key;
3944 struct wpa_eapol_ie_parse kde;
3945 size_t mic_len;
3946 u16 key_data_length;
3947#endif /* CONFIG_OCV */
3948
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003949 SM_ENTRY_MA(WPA_PTK_GROUP, REKEYESTABLISHED, wpa_ptk_group);
Hai Shalome21d4e82020-04-29 16:34:06 -07003950 sm->EAPOLKeyReceived = false;
Hai Shalom74f70d42019-02-11 14:42:39 -08003951
3952#ifdef CONFIG_OCV
3953 mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
3954
3955 /*
3956 * Note: last_rx_eapol_key length fields have already been validated in
3957 * wpa_receive().
3958 */
3959 hdr = (struct ieee802_1x_hdr *) sm->last_rx_eapol_key;
3960 key = (struct wpa_eapol_key *) (hdr + 1);
3961 mic = (u8 *) (key + 1);
3962 key_data = mic + mic_len + 2;
3963 key_data_length = WPA_GET_BE16(mic + mic_len);
3964 if (key_data_length > sm->last_rx_eapol_key_len - sizeof(*hdr) -
3965 sizeof(*key) - mic_len - 2)
3966 return;
3967
3968 if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) {
3969 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
3970 "received EAPOL-Key group msg 2/2 with invalid Key Data contents");
3971 return;
3972 }
3973
3974 if (wpa_auth_uses_ocv(sm)) {
3975 struct wpa_channel_info ci;
3976 int tx_chanwidth;
3977 int tx_seg1_idx;
3978
3979 if (wpa_channel_info(wpa_auth, &ci) != 0) {
3980 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalom899fcc72020-10-19 14:38:18 -07003981 "Failed to get channel info to validate received OCI in EAPOL-Key group 2/2");
Hai Shalom74f70d42019-02-11 14:42:39 -08003982 return;
3983 }
3984
3985 if (get_sta_tx_parameters(sm,
3986 channel_width_to_int(ci.chanwidth),
3987 ci.seg1_idx, &tx_chanwidth,
3988 &tx_seg1_idx) < 0)
3989 return;
3990
3991 if (ocv_verify_tx_params(kde.oci, kde.oci_len, &ci,
Hai Shalom899fcc72020-10-19 14:38:18 -07003992 tx_chanwidth, tx_seg1_idx) !=
3993 OCI_SUCCESS) {
3994 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
3995 "OCV failed: %s", ocv_errorstr);
3996 if (wpa_auth->conf.msg_ctx)
3997 wpa_msg(wpa_auth->conf.msg_ctx, MSG_INFO,
3998 OCV_FAILURE "addr=" MACSTR
3999 " frame=eapol-key-g2 error=%s",
4000 MAC2STR(sm->addr), ocv_errorstr);
Hai Shalom74f70d42019-02-11 14:42:39 -08004001 return;
4002 }
4003 }
4004#endif /* CONFIG_OCV */
4005
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004006 if (sm->GUpdateStationKeys)
4007 sm->group->GKeyDoneStations--;
Hai Shalome21d4e82020-04-29 16:34:06 -07004008 sm->GUpdateStationKeys = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004009 sm->GTimeoutCtr = 0;
4010 /* FIX: MLME.SetProtection.Request(TA, Tx_Rx) */
Hai Shalomfdcde762020-04-02 11:19:20 -07004011 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004012 "group key handshake completed (%s)",
4013 sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN");
Hai Shalome21d4e82020-04-29 16:34:06 -07004014 sm->has_GTK = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004015}
4016
4017
4018SM_STATE(WPA_PTK_GROUP, KEYERROR)
4019{
4020 SM_ENTRY_MA(WPA_PTK_GROUP, KEYERROR, wpa_ptk_group);
4021 if (sm->GUpdateStationKeys)
4022 sm->group->GKeyDoneStations--;
Hai Shalome21d4e82020-04-29 16:34:06 -07004023 sm->GUpdateStationKeys = false;
4024 sm->Disconnect = true;
4025 sm->disconnect_reason = WLAN_REASON_GROUP_KEY_UPDATE_TIMEOUT;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004026 wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO,
4027 "group key handshake failed (%s) after %u tries",
4028 sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN",
4029 sm->wpa_auth->conf.wpa_group_update_count);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004030}
4031
4032
4033SM_STEP(WPA_PTK_GROUP)
4034{
4035 if (sm->Init || sm->PtkGroupInit) {
4036 SM_ENTER(WPA_PTK_GROUP, IDLE);
Hai Shalome21d4e82020-04-29 16:34:06 -07004037 sm->PtkGroupInit = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004038 } else switch (sm->wpa_ptk_group_state) {
4039 case WPA_PTK_GROUP_IDLE:
4040 if (sm->GUpdateStationKeys ||
4041 (sm->wpa == WPA_VERSION_WPA && sm->PInitAKeys))
4042 SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING);
4043 break;
4044 case WPA_PTK_GROUP_REKEYNEGOTIATING:
4045 if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest &&
4046 !sm->EAPOLKeyPairwise && sm->MICVerified)
4047 SM_ENTER(WPA_PTK_GROUP, REKEYESTABLISHED);
4048 else if (sm->GTimeoutCtr >
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004049 sm->wpa_auth->conf.wpa_group_update_count ||
4050 (sm->wpa_auth->conf.wpa_disable_eapol_key_retries &&
4051 sm->GTimeoutCtr > 1))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004052 SM_ENTER(WPA_PTK_GROUP, KEYERROR);
4053 else if (sm->TimeoutEvt)
4054 SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING);
4055 break;
4056 case WPA_PTK_GROUP_KEYERROR:
4057 SM_ENTER(WPA_PTK_GROUP, IDLE);
4058 break;
4059 case WPA_PTK_GROUP_REKEYESTABLISHED:
4060 SM_ENTER(WPA_PTK_GROUP, IDLE);
4061 break;
4062 }
4063}
4064
4065
4066static int wpa_gtk_update(struct wpa_authenticator *wpa_auth,
4067 struct wpa_group *group)
4068{
Hai Shalomfdcde762020-04-02 11:19:20 -07004069 struct wpa_auth_config *conf = &wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004070 int ret = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07004071 size_t len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004072
4073 os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
4074 inc_byte_array(group->Counter, WPA_NONCE_LEN);
4075 if (wpa_gmk_to_gtk(group->GMK, "Group key expansion",
4076 wpa_auth->addr, group->GNonce,
4077 group->GTK[group->GN - 1], group->GTK_len) < 0)
4078 ret = -1;
4079 wpa_hexdump_key(MSG_DEBUG, "GTK",
4080 group->GTK[group->GN - 1], group->GTK_len);
4081
Hai Shalomfdcde762020-04-02 11:19:20 -07004082 if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
4083 len = wpa_cipher_key_len(conf->group_mgmt_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004084 os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
4085 inc_byte_array(group->Counter, WPA_NONCE_LEN);
4086 if (wpa_gmk_to_gtk(group->GMK, "IGTK key expansion",
4087 wpa_auth->addr, group->GNonce,
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004088 group->IGTK[group->GN_igtk - 4], len) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004089 ret = -1;
4090 wpa_hexdump_key(MSG_DEBUG, "IGTK",
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004091 group->IGTK[group->GN_igtk - 4], len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004092 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004093
Hai Shalomfdcde762020-04-02 11:19:20 -07004094 if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION &&
4095 conf->beacon_prot) {
4096 len = wpa_cipher_key_len(conf->group_mgmt_cipher);
4097 os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
4098 inc_byte_array(group->Counter, WPA_NONCE_LEN);
4099 if (wpa_gmk_to_gtk(group->GMK, "BIGTK key expansion",
4100 wpa_auth->addr, group->GNonce,
4101 group->BIGTK[group->GN_bigtk - 6], len) < 0)
4102 ret = -1;
4103 wpa_hexdump_key(MSG_DEBUG, "BIGTK",
4104 group->BIGTK[group->GN_bigtk - 6], len);
4105 }
4106
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004107 return ret;
4108}
4109
4110
4111static void wpa_group_gtk_init(struct wpa_authenticator *wpa_auth,
4112 struct wpa_group *group)
4113{
Hai Shalomfdcde762020-04-02 11:19:20 -07004114 wpa_printf(MSG_DEBUG,
4115 "WPA: group state machine entering state GTK_INIT (VLAN-ID %d)",
4116 group->vlan_id);
Hai Shalome21d4e82020-04-29 16:34:06 -07004117 group->changed = false; /* GInit is not cleared here; avoid loop */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004118 group->wpa_group_state = WPA_GROUP_GTK_INIT;
4119
4120 /* GTK[0..N] = 0 */
4121 os_memset(group->GTK, 0, sizeof(group->GTK));
4122 group->GN = 1;
4123 group->GM = 2;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004124 group->GN_igtk = 4;
4125 group->GM_igtk = 5;
Hai Shalomfdcde762020-04-02 11:19:20 -07004126 group->GN_bigtk = 6;
4127 group->GM_bigtk = 7;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004128 /* GTK[GN] = CalcGTK() */
4129 wpa_gtk_update(wpa_auth, group);
4130}
4131
4132
4133static int wpa_group_update_sta(struct wpa_state_machine *sm, void *ctx)
4134{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004135 if (ctx != NULL && ctx != sm->group)
4136 return 0;
4137
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004138 if (sm->wpa_ptk_state != WPA_PTK_PTKINITDONE) {
4139 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
4140 "Not in PTKINITDONE; skip Group Key update");
Hai Shalome21d4e82020-04-29 16:34:06 -07004141 sm->GUpdateStationKeys = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004142 return 0;
4143 }
4144 if (sm->GUpdateStationKeys) {
4145 /*
4146 * This should not really happen, so add a debug log entry.
4147 * Since we clear the GKeyDoneStations before the loop, the
4148 * station needs to be counted here anyway.
4149 */
4150 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07004151 "GUpdateStationKeys was already set when marking station for GTK rekeying");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004152 }
4153
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004154 /* Do not rekey GTK/IGTK when STA is in WNM-Sleep Mode */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004155 if (sm->is_wnmsleep)
4156 return 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004157
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004158 sm->group->GKeyDoneStations++;
Hai Shalome21d4e82020-04-29 16:34:06 -07004159 sm->GUpdateStationKeys = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004160
4161 wpa_sm_step(sm);
4162 return 0;
4163}
4164
4165
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004166#ifdef CONFIG_WNM_AP
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004167/* update GTK when exiting WNM-Sleep Mode */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004168void wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm)
4169{
Hai Shalomfdcde762020-04-02 11:19:20 -07004170 if (!sm || sm->is_wnmsleep)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004171 return;
4172
4173 wpa_group_update_sta(sm, NULL);
4174}
4175
4176
4177void wpa_set_wnmsleep(struct wpa_state_machine *sm, int flag)
4178{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004179 if (sm)
4180 sm->is_wnmsleep = !!flag;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004181}
4182
4183
4184int wpa_wnmsleep_gtk_subelem(struct wpa_state_machine *sm, u8 *pos)
4185{
Hai Shalom899fcc72020-10-19 14:38:18 -07004186 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004187 struct wpa_group *gsm = sm->group;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004188 u8 *start = pos;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004189
4190 /*
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004191 * GTK subelement:
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004192 * Sub-elem ID[1] | Length[1] | Key Info[2] | Key Length[1] | RSC[8] |
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004193 * Key[5..32]
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004194 */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004195 *pos++ = WNM_SLEEP_SUBELEM_GTK;
4196 *pos++ = 11 + gsm->GTK_len;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004197 /* Key ID in B0-B1 of Key Info */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004198 WPA_PUT_LE16(pos, gsm->GN & 0x03);
4199 pos += 2;
4200 *pos++ = gsm->GTK_len;
4201 if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, pos) != 0)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004202 return 0;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004203 pos += 8;
4204 os_memcpy(pos, gsm->GTK[gsm->GN - 1], gsm->GTK_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07004205 if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
4206 /*
4207 * Provide unique random GTK to each STA to prevent use
4208 * of GTK in the BSS.
4209 */
4210 if (random_get_bytes(pos, gsm->GTK_len) < 0)
4211 return 0;
4212 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004213 pos += gsm->GTK_len;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004214
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004215 wpa_printf(MSG_DEBUG, "WNM: GTK Key ID %u in WNM-Sleep Mode exit",
4216 gsm->GN);
4217 wpa_hexdump_key(MSG_DEBUG, "WNM: GTK in WNM-Sleep Mode exit",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004218 gsm->GTK[gsm->GN - 1], gsm->GTK_len);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004219
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004220 return pos - start;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004221}
4222
4223
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004224int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos)
4225{
Hai Shalom899fcc72020-10-19 14:38:18 -07004226 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004227 struct wpa_group *gsm = sm->group;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004228 u8 *start = pos;
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004229 size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004230
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004231 /*
4232 * IGTK subelement:
4233 * Sub-elem ID[1] | Length[1] | KeyID[2] | PN[6] | Key[16]
4234 */
4235 *pos++ = WNM_SLEEP_SUBELEM_IGTK;
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004236 *pos++ = 2 + 6 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004237 WPA_PUT_LE16(pos, gsm->GN_igtk);
4238 pos += 2;
4239 if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, pos) != 0)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004240 return 0;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004241 pos += 6;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004242
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004243 os_memcpy(pos, gsm->IGTK[gsm->GN_igtk - 4], len);
Hai Shalom899fcc72020-10-19 14:38:18 -07004244 if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
4245 /*
4246 * Provide unique random IGTK to each STA to prevent use
4247 * of IGTK in the BSS.
4248 */
4249 if (random_get_bytes(pos, len) < 0)
4250 return 0;
4251 }
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004252 pos += len;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004253
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004254 wpa_printf(MSG_DEBUG, "WNM: IGTK Key ID %u in WNM-Sleep Mode exit",
4255 gsm->GN_igtk);
4256 wpa_hexdump_key(MSG_DEBUG, "WNM: IGTK in WNM-Sleep Mode exit",
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004257 gsm->IGTK[gsm->GN_igtk - 4], len);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004258
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004259 return pos - start;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004260}
Hai Shalomc3565922019-10-28 11:58:20 -07004261
Hai Shalomfdcde762020-04-02 11:19:20 -07004262
4263int wpa_wnmsleep_bigtk_subelem(struct wpa_state_machine *sm, u8 *pos)
4264{
4265 struct wpa_group *gsm = sm->group;
4266 u8 *start = pos;
4267 size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
4268
4269 /*
4270 * BIGTK subelement:
4271 * Sub-elem ID[1] | Length[1] | KeyID[2] | PN[6] | Key[16]
4272 */
4273 *pos++ = WNM_SLEEP_SUBELEM_BIGTK;
4274 *pos++ = 2 + 6 + len;
4275 WPA_PUT_LE16(pos, gsm->GN_bigtk);
4276 pos += 2;
4277 if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_bigtk, pos) != 0)
4278 return 0;
4279 pos += 6;
4280
4281 os_memcpy(pos, gsm->BIGTK[gsm->GN_bigtk - 6], len);
Hai Shalom899fcc72020-10-19 14:38:18 -07004282 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
4283 /*
4284 * Provide unique random BIGTK to each STA to prevent use
4285 * of BIGTK in the BSS.
4286 */
4287 if (random_get_bytes(pos, len) < 0)
4288 return 0;
4289 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004290 pos += len;
4291
4292 wpa_printf(MSG_DEBUG, "WNM: BIGTK Key ID %u in WNM-Sleep Mode exit",
4293 gsm->GN_bigtk);
4294 wpa_hexdump_key(MSG_DEBUG, "WNM: BIGTK in WNM-Sleep Mode exit",
Hai Shaloma20dcd72022-02-04 13:43:00 -08004295 gsm->BIGTK[gsm->GN_bigtk - 6], len);
Hai Shalomfdcde762020-04-02 11:19:20 -07004296
4297 return pos - start;
4298}
4299
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004300#endif /* CONFIG_WNM_AP */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004301
4302
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004303static void wpa_group_setkeys(struct wpa_authenticator *wpa_auth,
4304 struct wpa_group *group)
4305{
4306 int tmp;
4307
Hai Shalomfdcde762020-04-02 11:19:20 -07004308 wpa_printf(MSG_DEBUG,
4309 "WPA: group state machine entering state SETKEYS (VLAN-ID %d)",
4310 group->vlan_id);
Hai Shalome21d4e82020-04-29 16:34:06 -07004311 group->changed = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004312 group->wpa_group_state = WPA_GROUP_SETKEYS;
Hai Shalome21d4e82020-04-29 16:34:06 -07004313 group->GTKReKey = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004314 tmp = group->GM;
4315 group->GM = group->GN;
4316 group->GN = tmp;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004317 tmp = group->GM_igtk;
4318 group->GM_igtk = group->GN_igtk;
4319 group->GN_igtk = tmp;
Hai Shalomfdcde762020-04-02 11:19:20 -07004320 tmp = group->GM_bigtk;
4321 group->GM_bigtk = group->GN_bigtk;
4322 group->GN_bigtk = tmp;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004323 /* "GKeyDoneStations = GNoStations" is done in more robust way by
4324 * counting the STAs that are marked with GUpdateStationKeys instead of
4325 * including all STAs that could be in not-yet-completed state. */
4326 wpa_gtk_update(wpa_auth, group);
4327
4328 if (group->GKeyDoneStations) {
Hai Shalomfdcde762020-04-02 11:19:20 -07004329 wpa_printf(MSG_DEBUG,
4330 "wpa_group_setkeys: Unexpected GKeyDoneStations=%d when starting new GTK rekey",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004331 group->GKeyDoneStations);
4332 group->GKeyDoneStations = 0;
4333 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004334 wpa_auth_for_each_sta(wpa_auth, wpa_group_update_sta, group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004335 wpa_printf(MSG_DEBUG, "wpa_group_setkeys: GKeyDoneStations=%d",
4336 group->GKeyDoneStations);
4337}
4338
4339
4340static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth,
4341 struct wpa_group *group)
4342{
Hai Shalomfdcde762020-04-02 11:19:20 -07004343 struct wpa_auth_config *conf = &wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004344 int ret = 0;
4345
4346 if (wpa_auth_set_key(wpa_auth, group->vlan_id,
Hai Shalomfdcde762020-04-02 11:19:20 -07004347 wpa_cipher_to_alg(conf->wpa_group),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004348 broadcast_ether_addr, group->GN,
Hai Shalomfdcde762020-04-02 11:19:20 -07004349 group->GTK[group->GN - 1], group->GTK_len,
4350 KEY_FLAG_GROUP_TX_DEFAULT) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004351 ret = -1;
4352
Hai Shalomfdcde762020-04-02 11:19:20 -07004353 if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004354 enum wpa_alg alg;
4355 size_t len;
4356
Hai Shalomfdcde762020-04-02 11:19:20 -07004357 alg = wpa_cipher_to_alg(conf->group_mgmt_cipher);
4358 len = wpa_cipher_key_len(conf->group_mgmt_cipher);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004359
4360 if (ret == 0 &&
4361 wpa_auth_set_key(wpa_auth, group->vlan_id, alg,
4362 broadcast_ether_addr, group->GN_igtk,
Hai Shalomfdcde762020-04-02 11:19:20 -07004363 group->IGTK[group->GN_igtk - 4], len,
4364 KEY_FLAG_GROUP_TX_DEFAULT) < 0)
4365 ret = -1;
4366
4367 if (ret == 0 && conf->beacon_prot &&
4368 wpa_auth_set_key(wpa_auth, group->vlan_id, alg,
4369 broadcast_ether_addr, group->GN_bigtk,
4370 group->BIGTK[group->GN_bigtk - 6], len,
4371 KEY_FLAG_GROUP_TX_DEFAULT) < 0)
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004372 ret = -1;
4373 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004374
4375 return ret;
4376}
4377
4378
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004379static int wpa_group_disconnect_cb(struct wpa_state_machine *sm, void *ctx)
4380{
4381 if (sm->group == ctx) {
4382 wpa_printf(MSG_DEBUG, "WPA: Mark STA " MACSTR
Hai Shalomfdcde762020-04-02 11:19:20 -07004383 " for disconnection due to fatal failure",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004384 MAC2STR(sm->addr));
Hai Shalome21d4e82020-04-29 16:34:06 -07004385 sm->Disconnect = true;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004386 }
4387
4388 return 0;
4389}
4390
4391
4392static void wpa_group_fatal_failure(struct wpa_authenticator *wpa_auth,
4393 struct wpa_group *group)
4394{
Hai Shalomfdcde762020-04-02 11:19:20 -07004395 wpa_printf(MSG_DEBUG,
4396 "WPA: group state machine entering state FATAL_FAILURE");
Hai Shalome21d4e82020-04-29 16:34:06 -07004397 group->changed = true;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004398 group->wpa_group_state = WPA_GROUP_FATAL_FAILURE;
4399 wpa_auth_for_each_sta(wpa_auth, wpa_group_disconnect_cb, group);
4400}
4401
4402
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004403static int wpa_group_setkeysdone(struct wpa_authenticator *wpa_auth,
4404 struct wpa_group *group)
4405{
Hai Shalomfdcde762020-04-02 11:19:20 -07004406 wpa_printf(MSG_DEBUG,
4407 "WPA: group state machine entering state SETKEYSDONE (VLAN-ID %d)",
4408 group->vlan_id);
Hai Shalome21d4e82020-04-29 16:34:06 -07004409 group->changed = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004410 group->wpa_group_state = WPA_GROUP_SETKEYSDONE;
4411
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004412 if (wpa_group_config_group_keys(wpa_auth, group) < 0) {
4413 wpa_group_fatal_failure(wpa_auth, group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004414 return -1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004415 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004416
4417 return 0;
4418}
4419
4420
4421static void wpa_group_sm_step(struct wpa_authenticator *wpa_auth,
4422 struct wpa_group *group)
4423{
4424 if (group->GInit) {
4425 wpa_group_gtk_init(wpa_auth, group);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004426 } else if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) {
4427 /* Do not allow group operations */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004428 } else if (group->wpa_group_state == WPA_GROUP_GTK_INIT &&
4429 group->GTKAuthenticator) {
4430 wpa_group_setkeysdone(wpa_auth, group);
4431 } else if (group->wpa_group_state == WPA_GROUP_SETKEYSDONE &&
4432 group->GTKReKey) {
4433 wpa_group_setkeys(wpa_auth, group);
4434 } else if (group->wpa_group_state == WPA_GROUP_SETKEYS) {
4435 if (group->GKeyDoneStations == 0)
4436 wpa_group_setkeysdone(wpa_auth, group);
4437 else if (group->GTKReKey)
4438 wpa_group_setkeys(wpa_auth, group);
4439 }
4440}
4441
4442
4443static int wpa_sm_step(struct wpa_state_machine *sm)
4444{
Hai Shalomfdcde762020-04-02 11:19:20 -07004445 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004446 return 0;
4447
4448 if (sm->in_step_loop) {
4449 /* This should not happen, but if it does, make sure we do not
4450 * end up freeing the state machine too early by exiting the
4451 * recursive call. */
4452 wpa_printf(MSG_ERROR, "WPA: wpa_sm_step() called recursively");
4453 return 0;
4454 }
4455
4456 sm->in_step_loop = 1;
4457 do {
4458 if (sm->pending_deinit)
4459 break;
4460
Hai Shalome21d4e82020-04-29 16:34:06 -07004461 sm->changed = false;
4462 sm->wpa_auth->group->changed = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004463
4464 SM_STEP_RUN(WPA_PTK);
4465 if (sm->pending_deinit)
4466 break;
4467 SM_STEP_RUN(WPA_PTK_GROUP);
4468 if (sm->pending_deinit)
4469 break;
4470 wpa_group_sm_step(sm->wpa_auth, sm->group);
4471 } while (sm->changed || sm->wpa_auth->group->changed);
4472 sm->in_step_loop = 0;
4473
4474 if (sm->pending_deinit) {
Hai Shalomfdcde762020-04-02 11:19:20 -07004475 wpa_printf(MSG_DEBUG,
4476 "WPA: Completing pending STA state machine deinit for "
4477 MACSTR, MAC2STR(sm->addr));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004478 wpa_free_sta_sm(sm);
4479 return 1;
4480 }
4481 return 0;
4482}
4483
4484
4485static void wpa_sm_call_step(void *eloop_ctx, void *timeout_ctx)
4486{
4487 struct wpa_state_machine *sm = eloop_ctx;
4488 wpa_sm_step(sm);
4489}
4490
4491
4492void wpa_auth_sm_notify(struct wpa_state_machine *sm)
4493{
Hai Shalomfdcde762020-04-02 11:19:20 -07004494 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004495 return;
4496 eloop_register_timeout(0, 0, wpa_sm_call_step, sm, NULL);
4497}
4498
4499
4500void wpa_gtk_rekey(struct wpa_authenticator *wpa_auth)
4501{
4502 int tmp, i;
4503 struct wpa_group *group;
4504
Hai Shalomfdcde762020-04-02 11:19:20 -07004505 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004506 return;
4507
4508 group = wpa_auth->group;
4509
4510 for (i = 0; i < 2; i++) {
4511 tmp = group->GM;
4512 group->GM = group->GN;
4513 group->GN = tmp;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004514 tmp = group->GM_igtk;
4515 group->GM_igtk = group->GN_igtk;
4516 group->GN_igtk = tmp;
Hai Shalomfdcde762020-04-02 11:19:20 -07004517 tmp = group->GM_bigtk;
4518 group->GM_bigtk = group->GN_bigtk;
4519 group->GN_bigtk = tmp;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004520 wpa_gtk_update(wpa_auth, group);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004521 wpa_group_config_group_keys(wpa_auth, group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004522 }
4523}
4524
4525
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004526static const char * wpa_bool_txt(int val)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004527{
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004528 return val ? "TRUE" : "FALSE";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004529}
4530
4531
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004532#define RSN_SUITE "%02x-%02x-%02x-%d"
4533#define RSN_SUITE_ARG(s) \
4534((s) >> 24) & 0xff, ((s) >> 16) & 0xff, ((s) >> 8) & 0xff, (s) & 0xff
4535
4536int wpa_get_mib(struct wpa_authenticator *wpa_auth, char *buf, size_t buflen)
4537{
Hai Shalomfdcde762020-04-02 11:19:20 -07004538 struct wpa_auth_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004539 int len = 0, ret;
4540 char pmkid_txt[PMKID_LEN * 2 + 1];
4541#ifdef CONFIG_RSN_PREAUTH
4542 const int preauth = 1;
4543#else /* CONFIG_RSN_PREAUTH */
4544 const int preauth = 0;
4545#endif /* CONFIG_RSN_PREAUTH */
4546
Hai Shalomfdcde762020-04-02 11:19:20 -07004547 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004548 return len;
Hai Shalomfdcde762020-04-02 11:19:20 -07004549 conf = &wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004550
4551 ret = os_snprintf(buf + len, buflen - len,
4552 "dot11RSNAOptionImplemented=TRUE\n"
4553 "dot11RSNAPreauthenticationImplemented=%s\n"
4554 "dot11RSNAEnabled=%s\n"
4555 "dot11RSNAPreauthenticationEnabled=%s\n",
4556 wpa_bool_txt(preauth),
Hai Shalomfdcde762020-04-02 11:19:20 -07004557 wpa_bool_txt(conf->wpa & WPA_PROTO_RSN),
4558 wpa_bool_txt(conf->rsn_preauth));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004559 if (os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004560 return len;
4561 len += ret;
4562
4563 wpa_snprintf_hex(pmkid_txt, sizeof(pmkid_txt),
4564 wpa_auth->dot11RSNAPMKIDUsed, PMKID_LEN);
4565
4566 ret = os_snprintf(
4567 buf + len, buflen - len,
4568 "dot11RSNAConfigVersion=%u\n"
4569 "dot11RSNAConfigPairwiseKeysSupported=9999\n"
4570 /* FIX: dot11RSNAConfigGroupCipher */
4571 /* FIX: dot11RSNAConfigGroupRekeyMethod */
4572 /* FIX: dot11RSNAConfigGroupRekeyTime */
4573 /* FIX: dot11RSNAConfigGroupRekeyPackets */
4574 "dot11RSNAConfigGroupRekeyStrict=%u\n"
4575 "dot11RSNAConfigGroupUpdateCount=%u\n"
4576 "dot11RSNAConfigPairwiseUpdateCount=%u\n"
4577 "dot11RSNAConfigGroupCipherSize=%u\n"
4578 "dot11RSNAConfigPMKLifetime=%u\n"
4579 "dot11RSNAConfigPMKReauthThreshold=%u\n"
4580 "dot11RSNAConfigNumberOfPTKSAReplayCounters=0\n"
4581 "dot11RSNAConfigSATimeout=%u\n"
4582 "dot11RSNAAuthenticationSuiteSelected=" RSN_SUITE "\n"
4583 "dot11RSNAPairwiseCipherSelected=" RSN_SUITE "\n"
4584 "dot11RSNAGroupCipherSelected=" RSN_SUITE "\n"
4585 "dot11RSNAPMKIDUsed=%s\n"
4586 "dot11RSNAAuthenticationSuiteRequested=" RSN_SUITE "\n"
4587 "dot11RSNAPairwiseCipherRequested=" RSN_SUITE "\n"
4588 "dot11RSNAGroupCipherRequested=" RSN_SUITE "\n"
4589 "dot11RSNATKIPCounterMeasuresInvoked=%u\n"
4590 "dot11RSNA4WayHandshakeFailures=%u\n"
4591 "dot11RSNAConfigNumberOfGTKSAReplayCounters=0\n",
4592 RSN_VERSION,
Hai Shalomfdcde762020-04-02 11:19:20 -07004593 !!conf->wpa_strict_rekey,
4594 conf->wpa_group_update_count,
4595 conf->wpa_pairwise_update_count,
4596 wpa_cipher_key_len(conf->wpa_group) * 8,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004597 dot11RSNAConfigPMKLifetime,
4598 dot11RSNAConfigPMKReauthThreshold,
4599 dot11RSNAConfigSATimeout,
4600 RSN_SUITE_ARG(wpa_auth->dot11RSNAAuthenticationSuiteSelected),
4601 RSN_SUITE_ARG(wpa_auth->dot11RSNAPairwiseCipherSelected),
4602 RSN_SUITE_ARG(wpa_auth->dot11RSNAGroupCipherSelected),
4603 pmkid_txt,
4604 RSN_SUITE_ARG(wpa_auth->dot11RSNAAuthenticationSuiteRequested),
4605 RSN_SUITE_ARG(wpa_auth->dot11RSNAPairwiseCipherRequested),
4606 RSN_SUITE_ARG(wpa_auth->dot11RSNAGroupCipherRequested),
4607 wpa_auth->dot11RSNATKIPCounterMeasuresInvoked,
4608 wpa_auth->dot11RSNA4WayHandshakeFailures);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004609 if (os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004610 return len;
4611 len += ret;
4612
4613 /* TODO: dot11RSNAConfigPairwiseCiphersTable */
4614 /* TODO: dot11RSNAConfigAuthenticationSuitesTable */
4615
4616 /* Private MIB */
4617 ret = os_snprintf(buf + len, buflen - len, "hostapdWPAGroupState=%d\n",
4618 wpa_auth->group->wpa_group_state);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004619 if (os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004620 return len;
4621 len += ret;
4622
4623 return len;
4624}
4625
4626
4627int wpa_get_mib_sta(struct wpa_state_machine *sm, char *buf, size_t buflen)
4628{
4629 int len = 0, ret;
4630 u32 pairwise = 0;
4631
Hai Shalomfdcde762020-04-02 11:19:20 -07004632 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004633 return 0;
4634
4635 /* TODO: FF-FF-FF-FF-FF-FF entry for broadcast/multicast stats */
4636
4637 /* dot11RSNAStatsEntry */
4638
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07004639 pairwise = wpa_cipher_to_suite(sm->wpa == WPA_VERSION_WPA2 ?
4640 WPA_PROTO_RSN : WPA_PROTO_WPA,
4641 sm->pairwise);
4642 if (pairwise == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004643 return 0;
4644
4645 ret = os_snprintf(
4646 buf + len, buflen - len,
4647 /* TODO: dot11RSNAStatsIndex */
4648 "dot11RSNAStatsSTAAddress=" MACSTR "\n"
4649 "dot11RSNAStatsVersion=1\n"
4650 "dot11RSNAStatsSelectedPairwiseCipher=" RSN_SUITE "\n"
4651 /* TODO: dot11RSNAStatsTKIPICVErrors */
4652 "dot11RSNAStatsTKIPLocalMICFailures=%u\n"
4653 "dot11RSNAStatsTKIPRemoteMICFailures=%u\n"
4654 /* TODO: dot11RSNAStatsCCMPReplays */
4655 /* TODO: dot11RSNAStatsCCMPDecryptErrors */
4656 /* TODO: dot11RSNAStatsTKIPReplays */,
4657 MAC2STR(sm->addr),
4658 RSN_SUITE_ARG(pairwise),
4659 sm->dot11RSNAStatsTKIPLocalMICFailures,
4660 sm->dot11RSNAStatsTKIPRemoteMICFailures);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004661 if (os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004662 return len;
4663 len += ret;
4664
4665 /* Private MIB */
4666 ret = os_snprintf(buf + len, buflen - len,
Hai Shalomc3565922019-10-28 11:58:20 -07004667 "wpa=%d\n"
4668 "AKMSuiteSelector=" RSN_SUITE "\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004669 "hostapdWPAPTKState=%d\n"
4670 "hostapdWPAPTKGroupState=%d\n",
Hai Shalomc3565922019-10-28 11:58:20 -07004671 sm->wpa,
4672 RSN_SUITE_ARG(wpa_akm_to_suite(sm->wpa_key_mgmt)),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004673 sm->wpa_ptk_state,
4674 sm->wpa_ptk_group_state);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004675 if (os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004676 return len;
4677 len += ret;
4678
4679 return len;
4680}
4681
4682
4683void wpa_auth_countermeasures_start(struct wpa_authenticator *wpa_auth)
4684{
4685 if (wpa_auth)
4686 wpa_auth->dot11RSNATKIPCounterMeasuresInvoked++;
4687}
4688
4689
4690int wpa_auth_pairwise_set(struct wpa_state_machine *sm)
4691{
4692 return sm && sm->pairwise_set;
4693}
4694
4695
4696int wpa_auth_get_pairwise(struct wpa_state_machine *sm)
4697{
4698 return sm->pairwise;
4699}
4700
4701
Hai Shalom74f70d42019-02-11 14:42:39 -08004702const u8 * wpa_auth_get_pmk(struct wpa_state_machine *sm, int *len)
4703{
4704 if (!sm)
4705 return NULL;
4706 *len = sm->pmk_len;
4707 return sm->PMK;
4708}
4709
4710
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004711int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm)
4712{
Hai Shalomfdcde762020-04-02 11:19:20 -07004713 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004714 return -1;
4715 return sm->wpa_key_mgmt;
4716}
4717
4718
4719int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm)
4720{
Hai Shalomfdcde762020-04-02 11:19:20 -07004721 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004722 return 0;
4723 return sm->wpa;
4724}
4725
4726
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02004727int wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm)
4728{
4729 if (!sm || !wpa_key_mgmt_ft(sm->wpa_key_mgmt))
4730 return 0;
4731 return sm->tk_already_set;
4732}
4733
4734
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004735int wpa_auth_sta_fils_tk_already_set(struct wpa_state_machine *sm)
4736{
4737 if (!sm || !wpa_key_mgmt_fils(sm->wpa_key_mgmt))
4738 return 0;
4739 return sm->tk_already_set;
4740}
4741
4742
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004743int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm,
4744 struct rsn_pmksa_cache_entry *entry)
4745{
Hai Shalomfdcde762020-04-02 11:19:20 -07004746 if (!sm || sm->pmksa != entry)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004747 return -1;
4748 sm->pmksa = NULL;
4749 return 0;
4750}
4751
4752
4753struct rsn_pmksa_cache_entry *
4754wpa_auth_sta_get_pmksa(struct wpa_state_machine *sm)
4755{
4756 return sm ? sm->pmksa : NULL;
4757}
4758
4759
4760void wpa_auth_sta_local_mic_failure_report(struct wpa_state_machine *sm)
4761{
4762 if (sm)
4763 sm->dot11RSNAStatsTKIPLocalMICFailures++;
4764}
4765
4766
4767const u8 * wpa_auth_get_wpa_ie(struct wpa_authenticator *wpa_auth, size_t *len)
4768{
Hai Shalomfdcde762020-04-02 11:19:20 -07004769 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004770 return NULL;
4771 *len = wpa_auth->wpa_ie_len;
4772 return wpa_auth->wpa_ie;
4773}
4774
4775
4776int wpa_auth_pmksa_add(struct wpa_state_machine *sm, const u8 *pmk,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004777 unsigned int pmk_len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004778 int session_timeout, struct eapol_state_machine *eapol)
4779{
Hai Shalomfdcde762020-04-02 11:19:20 -07004780 if (!sm || sm->wpa != WPA_VERSION_WPA2 ||
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07004781 sm->wpa_auth->conf.disable_pmksa_caching)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004782 return -1;
4783
Hai Shalom81f62d82019-07-22 12:10:00 -07004784#ifdef CONFIG_IEEE80211R_AP
4785 if (pmk_len >= 2 * PMK_LEN && wpa_key_mgmt_ft(sm->wpa_key_mgmt) &&
4786 wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) &&
4787 !wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) {
4788 /* Cache MPMK/XXKey instead of initial part from MSK */
4789 pmk = pmk + PMK_LEN;
4790 pmk_len = PMK_LEN;
4791 } else
4792#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004793 if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004794 if (pmk_len > PMK_LEN_SUITE_B_192)
4795 pmk_len = PMK_LEN_SUITE_B_192;
4796 } else if (pmk_len > PMK_LEN) {
4797 pmk_len = PMK_LEN;
4798 }
4799
Hai Shalom81f62d82019-07-22 12:10:00 -07004800 wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK", pmk, pmk_len);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004801 if (pmksa_cache_auth_add(sm->wpa_auth->pmksa, pmk, pmk_len, NULL,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004802 sm->PTK.kck, sm->PTK.kck_len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004803 sm->wpa_auth->addr, sm->addr, session_timeout,
4804 eapol, sm->wpa_key_mgmt))
4805 return 0;
4806
4807 return -1;
4808}
4809
4810
4811int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth,
4812 const u8 *pmk, size_t len, const u8 *sta_addr,
4813 int session_timeout,
4814 struct eapol_state_machine *eapol)
4815{
Hai Shalomfdcde762020-04-02 11:19:20 -07004816 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004817 return -1;
4818
Hai Shalom81f62d82019-07-22 12:10:00 -07004819 wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK from preauth", pmk, len);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004820 if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, len, NULL,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004821 NULL, 0,
4822 wpa_auth->addr,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004823 sta_addr, session_timeout, eapol,
4824 WPA_KEY_MGMT_IEEE8021X))
4825 return 0;
4826
4827 return -1;
4828}
4829
4830
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004831int wpa_auth_pmksa_add_sae(struct wpa_authenticator *wpa_auth, const u8 *addr,
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004832 const u8 *pmk, const u8 *pmkid)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004833{
4834 if (wpa_auth->conf.disable_pmksa_caching)
4835 return -1;
4836
Hai Shalom81f62d82019-07-22 12:10:00 -07004837 wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK from SAE", pmk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004838 if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, PMK_LEN, pmkid,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004839 NULL, 0,
4840 wpa_auth->addr, addr, 0, NULL,
4841 WPA_KEY_MGMT_SAE))
4842 return 0;
4843
4844 return -1;
4845}
4846
4847
Roshan Pius3a1667e2018-07-03 15:17:14 -07004848void wpa_auth_add_sae_pmkid(struct wpa_state_machine *sm, const u8 *pmkid)
4849{
4850 os_memcpy(sm->pmkid, pmkid, PMKID_LEN);
4851 sm->pmkid_set = 1;
4852}
4853
4854
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004855int wpa_auth_pmksa_add2(struct wpa_authenticator *wpa_auth, const u8 *addr,
4856 const u8 *pmk, size_t pmk_len, const u8 *pmkid,
4857 int session_timeout, int akmp)
4858{
Hai Shaloma20dcd72022-02-04 13:43:00 -08004859 if (!wpa_auth || wpa_auth->conf.disable_pmksa_caching)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004860 return -1;
4861
Hai Shalom81f62d82019-07-22 12:10:00 -07004862 wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK (2)", pmk, PMK_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004863 if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, pmk_len, pmkid,
4864 NULL, 0, wpa_auth->addr, addr, session_timeout,
4865 NULL, akmp))
4866 return 0;
4867
4868 return -1;
4869}
4870
4871
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004872void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth,
4873 const u8 *sta_addr)
4874{
4875 struct rsn_pmksa_cache_entry *pmksa;
4876
Hai Shalomfdcde762020-04-02 11:19:20 -07004877 if (!wpa_auth || !wpa_auth->pmksa)
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004878 return;
4879 pmksa = pmksa_cache_auth_get(wpa_auth->pmksa, sta_addr, NULL);
4880 if (pmksa) {
4881 wpa_printf(MSG_DEBUG, "WPA: Remove PMKSA cache entry for "
4882 MACSTR " based on request", MAC2STR(sta_addr));
4883 pmksa_cache_free_entry(wpa_auth->pmksa, pmksa);
4884 }
4885}
4886
4887
Dmitry Shmidte4663042016-04-04 10:07:49 -07004888int wpa_auth_pmksa_list(struct wpa_authenticator *wpa_auth, char *buf,
4889 size_t len)
4890{
4891 if (!wpa_auth || !wpa_auth->pmksa)
4892 return 0;
4893 return pmksa_cache_auth_list(wpa_auth->pmksa, buf, len);
4894}
4895
4896
4897void wpa_auth_pmksa_flush(struct wpa_authenticator *wpa_auth)
4898{
4899 if (wpa_auth && wpa_auth->pmksa)
4900 pmksa_cache_auth_flush(wpa_auth->pmksa);
4901}
4902
4903
Paul Stewart092955c2017-02-06 09:13:09 -08004904#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
4905#ifdef CONFIG_MESH
4906
4907int wpa_auth_pmksa_list_mesh(struct wpa_authenticator *wpa_auth, const u8 *addr,
4908 char *buf, size_t len)
4909{
4910 if (!wpa_auth || !wpa_auth->pmksa)
4911 return 0;
4912
4913 return pmksa_cache_auth_list_mesh(wpa_auth->pmksa, addr, buf, len);
4914}
4915
4916
4917struct rsn_pmksa_cache_entry *
4918wpa_auth_pmksa_create_entry(const u8 *aa, const u8 *spa, const u8 *pmk,
4919 const u8 *pmkid, int expiration)
4920{
4921 struct rsn_pmksa_cache_entry *entry;
4922 struct os_reltime now;
4923
4924 entry = pmksa_cache_auth_create_entry(pmk, PMK_LEN, pmkid, NULL, 0, aa,
4925 spa, 0, NULL, WPA_KEY_MGMT_SAE);
4926 if (!entry)
4927 return NULL;
4928
4929 os_get_reltime(&now);
4930 entry->expiration = now.sec + expiration;
4931 return entry;
4932}
4933
4934
4935int wpa_auth_pmksa_add_entry(struct wpa_authenticator *wpa_auth,
4936 struct rsn_pmksa_cache_entry *entry)
4937{
4938 int ret;
4939
4940 if (!wpa_auth || !wpa_auth->pmksa)
4941 return -1;
4942
4943 ret = pmksa_cache_auth_add_entry(wpa_auth->pmksa, entry);
4944 if (ret < 0)
4945 wpa_printf(MSG_DEBUG,
4946 "RSN: Failed to store external PMKSA cache for "
4947 MACSTR, MAC2STR(entry->spa));
4948
4949 return ret;
4950}
4951
4952#endif /* CONFIG_MESH */
4953#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
4954
4955
Dmitry Shmidte4663042016-04-04 10:07:49 -07004956struct rsn_pmksa_cache_entry *
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004957wpa_auth_pmksa_get(struct wpa_authenticator *wpa_auth, const u8 *sta_addr,
4958 const u8 *pmkid)
Dmitry Shmidte4663042016-04-04 10:07:49 -07004959{
4960 if (!wpa_auth || !wpa_auth->pmksa)
4961 return NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004962 return pmksa_cache_auth_get(wpa_auth->pmksa, sta_addr, pmkid);
Dmitry Shmidte4663042016-04-04 10:07:49 -07004963}
4964
4965
4966void wpa_auth_pmksa_set_to_sm(struct rsn_pmksa_cache_entry *pmksa,
4967 struct wpa_state_machine *sm,
4968 struct wpa_authenticator *wpa_auth,
4969 u8 *pmkid, u8 *pmk)
4970{
4971 if (!sm)
4972 return;
4973
4974 sm->pmksa = pmksa;
4975 os_memcpy(pmk, pmksa->pmk, PMK_LEN);
4976 os_memcpy(pmkid, pmksa->pmkid, PMKID_LEN);
4977 os_memcpy(wpa_auth->dot11RSNAPMKIDUsed, pmksa->pmkid, PMKID_LEN);
4978}
4979
4980
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004981/*
4982 * Remove and free the group from wpa_authenticator. This is triggered by a
4983 * callback to make sure nobody is currently iterating the group list while it
4984 * gets modified.
4985 */
4986static void wpa_group_free(struct wpa_authenticator *wpa_auth,
4987 struct wpa_group *group)
4988{
4989 struct wpa_group *prev = wpa_auth->group;
4990
4991 wpa_printf(MSG_DEBUG, "WPA: Remove group state machine for VLAN-ID %d",
4992 group->vlan_id);
4993
4994 while (prev) {
4995 if (prev->next == group) {
4996 /* This never frees the special first group as needed */
4997 prev->next = group->next;
4998 os_free(group);
4999 break;
5000 }
5001 prev = prev->next;
5002 }
5003
5004}
5005
5006
5007/* Increase the reference counter for group */
5008static void wpa_group_get(struct wpa_authenticator *wpa_auth,
5009 struct wpa_group *group)
5010{
5011 /* Skip the special first group */
5012 if (wpa_auth->group == group)
5013 return;
5014
5015 group->references++;
5016}
5017
5018
5019/* Decrease the reference counter and maybe free the group */
5020static void wpa_group_put(struct wpa_authenticator *wpa_auth,
5021 struct wpa_group *group)
5022{
5023 /* Skip the special first group */
5024 if (wpa_auth->group == group)
5025 return;
5026
5027 group->references--;
5028 if (group->references)
5029 return;
5030 wpa_group_free(wpa_auth, group);
5031}
5032
5033
5034/*
5035 * Add a group that has its references counter set to zero. Caller needs to
5036 * call wpa_group_get() on the return value to mark the entry in use.
5037 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005038static struct wpa_group *
5039wpa_auth_add_group(struct wpa_authenticator *wpa_auth, int vlan_id)
5040{
5041 struct wpa_group *group;
5042
Hai Shalomfdcde762020-04-02 11:19:20 -07005043 if (!wpa_auth || !wpa_auth->group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005044 return NULL;
5045
5046 wpa_printf(MSG_DEBUG, "WPA: Add group state machine for VLAN-ID %d",
5047 vlan_id);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005048 group = wpa_group_init(wpa_auth, vlan_id, 0);
Hai Shalomfdcde762020-04-02 11:19:20 -07005049 if (!group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005050 return NULL;
5051
5052 group->next = wpa_auth->group->next;
5053 wpa_auth->group->next = group;
5054
5055 return group;
5056}
5057
5058
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005059/*
5060 * Enforce that the group state machine for the VLAN is running, increase
5061 * reference counter as interface is up. References might have been increased
5062 * even if a negative value is returned.
5063 * Returns: -1 on error (group missing, group already failed); otherwise, 0
5064 */
5065int wpa_auth_ensure_group(struct wpa_authenticator *wpa_auth, int vlan_id)
5066{
5067 struct wpa_group *group;
5068
Hai Shalomfdcde762020-04-02 11:19:20 -07005069 if (!wpa_auth)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005070 return 0;
5071
5072 group = wpa_auth->group;
5073 while (group) {
5074 if (group->vlan_id == vlan_id)
5075 break;
5076 group = group->next;
5077 }
5078
Hai Shalomfdcde762020-04-02 11:19:20 -07005079 if (!group) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005080 group = wpa_auth_add_group(wpa_auth, vlan_id);
Hai Shalomfdcde762020-04-02 11:19:20 -07005081 if (!group)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005082 return -1;
5083 }
5084
5085 wpa_printf(MSG_DEBUG,
5086 "WPA: Ensure group state machine running for VLAN ID %d",
5087 vlan_id);
5088
5089 wpa_group_get(wpa_auth, group);
5090 group->num_setup_iface++;
5091
5092 if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
5093 return -1;
5094
5095 return 0;
5096}
5097
5098
5099/*
5100 * Decrease reference counter, expected to be zero afterwards.
5101 * returns: -1 on error (group not found, group in fail state)
5102 * -2 if wpa_group is still referenced
5103 * 0 else
5104 */
5105int wpa_auth_release_group(struct wpa_authenticator *wpa_auth, int vlan_id)
5106{
5107 struct wpa_group *group;
5108 int ret = 0;
5109
Hai Shalomfdcde762020-04-02 11:19:20 -07005110 if (!wpa_auth)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005111 return 0;
5112
5113 group = wpa_auth->group;
5114 while (group) {
5115 if (group->vlan_id == vlan_id)
5116 break;
5117 group = group->next;
5118 }
5119
Hai Shalomfdcde762020-04-02 11:19:20 -07005120 if (!group)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005121 return -1;
5122
5123 wpa_printf(MSG_DEBUG,
5124 "WPA: Try stopping group state machine for VLAN ID %d",
5125 vlan_id);
5126
5127 if (group->num_setup_iface <= 0) {
5128 wpa_printf(MSG_ERROR,
5129 "WPA: wpa_auth_release_group called more often than wpa_auth_ensure_group for VLAN ID %d, skipping.",
5130 vlan_id);
5131 return -1;
5132 }
5133 group->num_setup_iface--;
5134
5135 if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
5136 ret = -1;
5137
5138 if (group->references > 1) {
5139 wpa_printf(MSG_DEBUG,
5140 "WPA: Cannot stop group state machine for VLAN ID %d as references are still hold",
5141 vlan_id);
5142 ret = -2;
5143 }
5144
5145 wpa_group_put(wpa_auth, group);
5146
5147 return ret;
5148}
5149
5150
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005151int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id)
5152{
5153 struct wpa_group *group;
5154
Hai Shalomfdcde762020-04-02 11:19:20 -07005155 if (!sm || !sm->wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005156 return 0;
5157
5158 group = sm->wpa_auth->group;
5159 while (group) {
5160 if (group->vlan_id == vlan_id)
5161 break;
5162 group = group->next;
5163 }
5164
Hai Shalomfdcde762020-04-02 11:19:20 -07005165 if (!group) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005166 group = wpa_auth_add_group(sm->wpa_auth, vlan_id);
Hai Shalomfdcde762020-04-02 11:19:20 -07005167 if (!group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005168 return -1;
5169 }
5170
5171 if (sm->group == group)
5172 return 0;
5173
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005174 if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
5175 return -1;
5176
Hai Shalomfdcde762020-04-02 11:19:20 -07005177 wpa_printf(MSG_DEBUG, "WPA: Moving STA " MACSTR
5178 " to use group state machine for VLAN ID %d",
5179 MAC2STR(sm->addr), vlan_id);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005180
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005181 wpa_group_get(sm->wpa_auth, group);
5182 wpa_group_put(sm->wpa_auth, sm->group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005183 sm->group = group;
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005184
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005185 return 0;
5186}
5187
5188
5189void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth,
5190 struct wpa_state_machine *sm, int ack)
5191{
Hai Shalomfdcde762020-04-02 11:19:20 -07005192 if (!wpa_auth || !sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005193 return;
5194 wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key TX status for STA " MACSTR
5195 " ack=%d", MAC2STR(sm->addr), ack);
5196 if (sm->pending_1_of_4_timeout && ack) {
5197 /*
5198 * Some deployed supplicant implementations update their SNonce
5199 * for each EAPOL-Key 2/4 message even within the same 4-way
5200 * handshake and then fail to use the first SNonce when
5201 * deriving the PTK. This results in unsuccessful 4-way
5202 * handshake whenever the relatively short initial timeout is
5203 * reached and EAPOL-Key 1/4 is retransmitted. Try to work
5204 * around this by increasing the timeout now that we know that
5205 * the station has received the frame.
5206 */
5207 int timeout_ms = eapol_key_timeout_subseq;
Hai Shalomfdcde762020-04-02 11:19:20 -07005208 wpa_printf(MSG_DEBUG,
5209 "WPA: Increase initial EAPOL-Key 1/4 timeout by %u ms because of acknowledged frame",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005210 timeout_ms);
5211 eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm);
5212 eloop_register_timeout(timeout_ms / 1000,
5213 (timeout_ms % 1000) * 1000,
5214 wpa_send_eapol_timeout, wpa_auth, sm);
5215 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005216
5217#ifdef CONFIG_TESTING_OPTIONS
5218 if (sm->eapol_status_cb) {
5219 sm->eapol_status_cb(sm->eapol_status_cb_ctx1,
5220 sm->eapol_status_cb_ctx2);
5221 sm->eapol_status_cb = NULL;
5222 }
5223#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005224}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005225
5226
5227int wpa_auth_uses_sae(struct wpa_state_machine *sm)
5228{
Hai Shalomfdcde762020-04-02 11:19:20 -07005229 if (!sm)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005230 return 0;
5231 return wpa_key_mgmt_sae(sm->wpa_key_mgmt);
5232}
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005233
5234
5235int wpa_auth_uses_ft_sae(struct wpa_state_machine *sm)
5236{
Hai Shalomfdcde762020-04-02 11:19:20 -07005237 if (!sm)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005238 return 0;
5239 return sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_SAE;
5240}
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08005241
5242
5243#ifdef CONFIG_P2P
5244int wpa_auth_get_ip_addr(struct wpa_state_machine *sm, u8 *addr)
5245{
Hai Shalomfdcde762020-04-02 11:19:20 -07005246 if (!sm || WPA_GET_BE32(sm->ip_addr) == 0)
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08005247 return -1;
5248 os_memcpy(addr, sm->ip_addr, 4);
5249 return 0;
5250}
5251#endif /* CONFIG_P2P */
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08005252
5253
5254int wpa_auth_radius_das_disconnect_pmksa(struct wpa_authenticator *wpa_auth,
5255 struct radius_das_attrs *attr)
5256{
5257 return pmksa_cache_auth_radius_das_disconnect(wpa_auth->pmksa, attr);
5258}
Dmitry Shmidt7f656022015-02-25 14:36:37 -08005259
5260
5261void wpa_auth_reconfig_group_keys(struct wpa_authenticator *wpa_auth)
5262{
5263 struct wpa_group *group;
5264
5265 if (!wpa_auth)
5266 return;
5267 for (group = wpa_auth->group; group; group = group->next)
5268 wpa_group_config_group_keys(wpa_auth, group);
5269}
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005270
5271
5272#ifdef CONFIG_FILS
5273
5274struct wpa_auth_fils_iter_data {
5275 struct wpa_authenticator *auth;
5276 const u8 *cache_id;
5277 struct rsn_pmksa_cache_entry *pmksa;
5278 const u8 *spa;
5279 const u8 *pmkid;
5280};
5281
5282
5283static int wpa_auth_fils_iter(struct wpa_authenticator *a, void *ctx)
5284{
5285 struct wpa_auth_fils_iter_data *data = ctx;
5286
5287 if (a == data->auth || !a->conf.fils_cache_id_set ||
5288 os_memcmp(a->conf.fils_cache_id, data->cache_id,
5289 FILS_CACHE_ID_LEN) != 0)
5290 return 0;
5291 data->pmksa = pmksa_cache_auth_get(a->pmksa, data->spa, data->pmkid);
5292 return data->pmksa != NULL;
5293}
5294
5295
5296struct rsn_pmksa_cache_entry *
5297wpa_auth_pmksa_get_fils_cache_id(struct wpa_authenticator *wpa_auth,
5298 const u8 *sta_addr, const u8 *pmkid)
5299{
5300 struct wpa_auth_fils_iter_data idata;
5301
5302 if (!wpa_auth->conf.fils_cache_id_set)
5303 return NULL;
5304 idata.auth = wpa_auth;
5305 idata.cache_id = wpa_auth->conf.fils_cache_id;
5306 idata.pmksa = NULL;
5307 idata.spa = sta_addr;
5308 idata.pmkid = pmkid;
5309 wpa_auth_for_each_auth(wpa_auth, wpa_auth_fils_iter, &idata);
5310 return idata.pmksa;
5311}
5312
5313
5314#ifdef CONFIG_IEEE80211R_AP
Roshan Pius3a1667e2018-07-03 15:17:14 -07005315int wpa_auth_write_fte(struct wpa_authenticator *wpa_auth, int use_sha384,
5316 u8 *buf, size_t len)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005317{
5318 struct wpa_auth_config *conf = &wpa_auth->conf;
5319
Roshan Pius3a1667e2018-07-03 15:17:14 -07005320 return wpa_write_ftie(conf, use_sha384, conf->r0_key_holder,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005321 conf->r0_key_holder_len,
Hai Shalomfdcde762020-04-02 11:19:20 -07005322 NULL, NULL, buf, len, NULL, 0, 0);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005323}
5324#endif /* CONFIG_IEEE80211R_AP */
5325
5326
5327void wpa_auth_get_fils_aead_params(struct wpa_state_machine *sm,
5328 u8 *fils_anonce, u8 *fils_snonce,
5329 u8 *fils_kek, size_t *fils_kek_len)
5330{
5331 os_memcpy(fils_anonce, sm->ANonce, WPA_NONCE_LEN);
5332 os_memcpy(fils_snonce, sm->SNonce, WPA_NONCE_LEN);
5333 os_memcpy(fils_kek, sm->PTK.kek, WPA_KEK_MAX_LEN);
5334 *fils_kek_len = sm->PTK.kek_len;
5335}
5336
Hai Shalom81f62d82019-07-22 12:10:00 -07005337
5338void wpa_auth_add_fils_pmk_pmkid(struct wpa_state_machine *sm, const u8 *pmk,
5339 size_t pmk_len, const u8 *pmkid)
5340{
5341 os_memcpy(sm->PMK, pmk, pmk_len);
5342 sm->pmk_len = pmk_len;
5343 os_memcpy(sm->pmkid, pmkid, PMKID_LEN);
5344 sm->pmkid_set = 1;
5345}
5346
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005347#endif /* CONFIG_FILS */
5348
5349
Hai Shalom021b0b52019-04-10 11:17:58 -07005350void wpa_auth_set_auth_alg(struct wpa_state_machine *sm, u16 auth_alg)
5351{
5352 if (sm)
5353 sm->auth_alg = auth_alg;
5354}
5355
5356
5357#ifdef CONFIG_DPP2
5358void wpa_auth_set_dpp_z(struct wpa_state_machine *sm, const struct wpabuf *z)
5359{
5360 if (sm) {
5361 wpabuf_clear_free(sm->dpp_z);
5362 sm->dpp_z = z ? wpabuf_dup(z) : NULL;
5363 }
5364}
5365#endif /* CONFIG_DPP2 */
5366
5367
Hai Shalom899fcc72020-10-19 14:38:18 -07005368void wpa_auth_set_transition_disable(struct wpa_authenticator *wpa_auth,
5369 u8 val)
5370{
5371 if (wpa_auth)
5372 wpa_auth->conf.transition_disable = val;
5373}
5374
5375
Roshan Pius3a1667e2018-07-03 15:17:14 -07005376#ifdef CONFIG_TESTING_OPTIONS
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005377
5378int wpa_auth_resend_m1(struct wpa_state_machine *sm, int change_anonce,
5379 void (*cb)(void *ctx1, void *ctx2),
5380 void *ctx1, void *ctx2)
5381{
5382 const u8 *anonce = sm->ANonce;
5383 u8 anonce_buf[WPA_NONCE_LEN];
5384
5385 if (change_anonce) {
5386 if (random_get_bytes(anonce_buf, WPA_NONCE_LEN))
5387 return -1;
5388 anonce = anonce_buf;
5389 }
5390
5391 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
5392 "sending 1/4 msg of 4-Way Handshake (TESTING)");
5393 wpa_send_eapol(sm->wpa_auth, sm,
5394 WPA_KEY_INFO_ACK | WPA_KEY_INFO_KEY_TYPE, NULL,
5395 anonce, NULL, 0, 0, 0);
5396 return 0;
5397}
5398
5399
5400int wpa_auth_resend_m3(struct wpa_state_machine *sm,
5401 void (*cb)(void *ctx1, void *ctx2),
5402 void *ctx1, void *ctx2)
5403{
Roshan Pius3a1667e2018-07-03 15:17:14 -07005404 u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde, *pos;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005405 u8 *opos;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005406 size_t gtk_len, kde_len;
Hai Shalom899fcc72020-10-19 14:38:18 -07005407 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005408 struct wpa_group *gsm = sm->group;
5409 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07005410 int wpa_ie_len, secure, gtkidx, encr = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07005411 u8 hdr[2];
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005412
5413 /* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, [MDIE],
Hai Shalomfdcde762020-04-02 11:19:20 -07005414 GTK[GN], IGTK, [BIGTK], [FTIE], [TIE * 2])
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005415 */
5416
5417 /* Use 0 RSC */
5418 os_memset(rsc, 0, WPA_KEY_RSC_LEN);
5419 /* If FT is used, wpa_auth->wpa_ie includes both RSNIE and MDIE */
5420 wpa_ie = sm->wpa_auth->wpa_ie;
5421 wpa_ie_len = sm->wpa_auth->wpa_ie_len;
5422 if (sm->wpa == WPA_VERSION_WPA &&
5423 (sm->wpa_auth->conf.wpa & WPA_PROTO_RSN) &&
5424 wpa_ie_len > wpa_ie[1] + 2 && wpa_ie[0] == WLAN_EID_RSN) {
5425 /* WPA-only STA, remove RSN IE and possible MDIE */
5426 wpa_ie = wpa_ie + wpa_ie[1] + 2;
Hai Shalom60840252021-02-19 19:02:11 -08005427 if (wpa_ie[0] == WLAN_EID_RSNX)
5428 wpa_ie = wpa_ie + wpa_ie[1] + 2;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005429 if (wpa_ie[0] == WLAN_EID_MOBILITY_DOMAIN)
5430 wpa_ie = wpa_ie + wpa_ie[1] + 2;
5431 wpa_ie_len = wpa_ie[1] + 2;
5432 }
5433 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
5434 "sending 3/4 msg of 4-Way Handshake (TESTING)");
5435 if (sm->wpa == WPA_VERSION_WPA2) {
5436 /* WPA2 send GTK in the 4-way handshake */
5437 secure = 1;
5438 gtk = gsm->GTK[gsm->GN - 1];
5439 gtk_len = gsm->GTK_len;
Hai Shalomc3565922019-10-28 11:58:20 -07005440 gtkidx = gsm->GN;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005441 _rsc = rsc;
5442 encr = 1;
5443 } else {
5444 /* WPA does not include GTK in msg 3/4 */
5445 secure = 0;
5446 gtk = NULL;
5447 gtk_len = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005448 _rsc = NULL;
5449 if (sm->rx_eapol_key_secure) {
5450 /*
5451 * It looks like Windows 7 supplicant tries to use
5452 * Secure bit in msg 2/4 after having reported Michael
5453 * MIC failure and it then rejects the 4-way handshake
5454 * if msg 3/4 does not set Secure bit. Work around this
5455 * by setting the Secure bit here even in the case of
5456 * WPA if the supplicant used it first.
5457 */
5458 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07005459 "STA used Secure bit in WPA msg 2/4 - set Secure for 3/4 as workaround");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005460 secure = 1;
5461 }
5462 }
5463
Hai Shalom74f70d42019-02-11 14:42:39 -08005464 kde_len = wpa_ie_len + ieee80211w_kde_len(sm) + ocv_oci_len(sm);
Hai Shalomfdcde762020-04-02 11:19:20 -07005465
5466 if (sm->use_ext_key_id)
5467 kde_len += 2 + RSN_SELECTOR_LEN + 2;
5468
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005469 if (gtk)
5470 kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len;
5471#ifdef CONFIG_IEEE80211R_AP
5472 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
5473 kde_len += 2 + PMKID_LEN; /* PMKR1Name into RSN IE */
5474 kde_len += 300; /* FTIE + 2 * TIE */
5475 }
5476#endif /* CONFIG_IEEE80211R_AP */
5477 kde = os_malloc(kde_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07005478 if (!kde)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005479 return -1;
5480
5481 pos = kde;
5482 os_memcpy(pos, wpa_ie, wpa_ie_len);
5483 pos += wpa_ie_len;
5484#ifdef CONFIG_IEEE80211R_AP
5485 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
5486 int res;
5487 size_t elen;
5488
5489 elen = pos - kde;
5490 res = wpa_insert_pmkid(kde, &elen, sm->pmk_r1_name);
5491 if (res < 0) {
Hai Shalomfdcde762020-04-02 11:19:20 -07005492 wpa_printf(MSG_ERROR,
5493 "FT: Failed to insert PMKR1Name into RSN IE in EAPOL-Key data");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005494 os_free(kde);
5495 return -1;
5496 }
5497 pos -= wpa_ie_len;
5498 pos += elen;
5499 }
5500#endif /* CONFIG_IEEE80211R_AP */
Hai Shalomfdcde762020-04-02 11:19:20 -07005501 hdr[1] = 0;
5502
5503 if (sm->use_ext_key_id) {
5504 hdr[0] = sm->keyidx_active & 0x01;
5505 pos = wpa_add_kde(pos, RSN_KEY_DATA_KEYID, hdr, 2, NULL, 0);
5506 }
5507
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005508 if (gtk) {
Hai Shalomc3565922019-10-28 11:58:20 -07005509 hdr[0] = gtkidx & 0x03;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005510 pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
5511 gtk, gtk_len);
5512 }
5513 opos = pos;
5514 pos = ieee80211w_kde_add(sm, pos);
Roshan Pius3a1667e2018-07-03 15:17:14 -07005515 if (pos - opos >= 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN) {
5516 /* skip KDE header and keyid */
5517 opos += 2 + RSN_SELECTOR_LEN + 2;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005518 os_memset(opos, 0, 6); /* clear PN */
5519 }
Hai Shalom899fcc72020-10-19 14:38:18 -07005520 if (ocv_oci_add(sm, &pos, conf->oci_freq_override_eapol_m3) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -08005521 os_free(kde);
5522 return -1;
5523 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005524
5525#ifdef CONFIG_IEEE80211R_AP
5526 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
5527 int res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005528
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005529 if (sm->assoc_resp_ftie &&
5530 kde + kde_len - pos >= 2 + sm->assoc_resp_ftie[1]) {
5531 os_memcpy(pos, sm->assoc_resp_ftie,
5532 2 + sm->assoc_resp_ftie[1]);
5533 res = 2 + sm->assoc_resp_ftie[1];
5534 } else {
Roshan Pius3a1667e2018-07-03 15:17:14 -07005535 int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt);
5536
5537 res = wpa_write_ftie(conf, use_sha384,
5538 conf->r0_key_holder,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005539 conf->r0_key_holder_len,
5540 NULL, NULL, pos,
5541 kde + kde_len - pos,
Hai Shalomfdcde762020-04-02 11:19:20 -07005542 NULL, 0, 0);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005543 }
5544 if (res < 0) {
Hai Shalomfdcde762020-04-02 11:19:20 -07005545 wpa_printf(MSG_ERROR,
5546 "FT: Failed to insert FTIE into EAPOL-Key Key Data");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005547 os_free(kde);
5548 return -1;
5549 }
5550 pos += res;
5551
5552 /* TIE[ReassociationDeadline] (TU) */
5553 *pos++ = WLAN_EID_TIMEOUT_INTERVAL;
5554 *pos++ = 5;
5555 *pos++ = WLAN_TIMEOUT_REASSOC_DEADLINE;
5556 WPA_PUT_LE32(pos, conf->reassociation_deadline);
5557 pos += 4;
5558
5559 /* TIE[KeyLifetime] (seconds) */
5560 *pos++ = WLAN_EID_TIMEOUT_INTERVAL;
5561 *pos++ = 5;
5562 *pos++ = WLAN_TIMEOUT_KEY_LIFETIME;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005563 WPA_PUT_LE32(pos, conf->r0_key_lifetime);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005564 pos += 4;
5565 }
5566#endif /* CONFIG_IEEE80211R_AP */
5567
5568 wpa_send_eapol(sm->wpa_auth, sm,
5569 (secure ? WPA_KEY_INFO_SECURE : 0) |
5570 (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
5571 WPA_KEY_INFO_MIC : 0) |
5572 WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL |
5573 WPA_KEY_INFO_KEY_TYPE,
Hai Shalomc3565922019-10-28 11:58:20 -07005574 _rsc, sm->ANonce, kde, pos - kde, 0, encr);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005575 os_free(kde);
5576 return 0;
5577}
5578
5579
5580int wpa_auth_resend_group_m1(struct wpa_state_machine *sm,
5581 void (*cb)(void *ctx1, void *ctx2),
5582 void *ctx1, void *ctx2)
5583{
5584 u8 rsc[WPA_KEY_RSC_LEN];
Hai Shalom899fcc72020-10-19 14:38:18 -07005585 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005586 struct wpa_group *gsm = sm->group;
5587 const u8 *kde;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005588 u8 *kde_buf = NULL, *pos, hdr[2];
Roshan Pius3a1667e2018-07-03 15:17:14 -07005589 u8 *opos;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005590 size_t kde_len;
5591 u8 *gtk;
5592
5593 /* Send EAPOL(1, 1, 1, !Pair, G, RSC, GNonce, MIC(PTK), GTK[GN]) */
5594 os_memset(rsc, 0, WPA_KEY_RSC_LEN);
5595 /* Use 0 RSC */
5596 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
5597 "sending 1/2 msg of Group Key Handshake (TESTING)");
5598
5599 gtk = gsm->GTK[gsm->GN - 1];
5600 if (sm->wpa == WPA_VERSION_WPA2) {
5601 kde_len = 2 + RSN_SELECTOR_LEN + 2 + gsm->GTK_len +
Hai Shalom74f70d42019-02-11 14:42:39 -08005602 ieee80211w_kde_len(sm) + ocv_oci_len(sm);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005603 kde_buf = os_malloc(kde_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07005604 if (!kde_buf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005605 return -1;
5606
5607 kde = pos = kde_buf;
5608 hdr[0] = gsm->GN & 0x03;
5609 hdr[1] = 0;
5610 pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
5611 gtk, gsm->GTK_len);
5612 opos = pos;
5613 pos = ieee80211w_kde_add(sm, pos);
Roshan Pius3a1667e2018-07-03 15:17:14 -07005614 if (pos - opos >=
5615 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN) {
5616 /* skip KDE header and keyid */
5617 opos += 2 + RSN_SELECTOR_LEN + 2;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005618 os_memset(opos, 0, 6); /* clear PN */
5619 }
Hai Shalom899fcc72020-10-19 14:38:18 -07005620 if (ocv_oci_add(sm, &pos,
5621 conf->oci_freq_override_eapol_g1) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -08005622 os_free(kde_buf);
5623 return -1;
5624 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005625 kde_len = pos - kde;
5626 } else {
5627 kde = gtk;
5628 kde_len = gsm->GTK_len;
5629 }
5630
5631 sm->eapol_status_cb = cb;
5632 sm->eapol_status_cb_ctx1 = ctx1;
5633 sm->eapol_status_cb_ctx2 = ctx2;
5634
5635 wpa_send_eapol(sm->wpa_auth, sm,
5636 WPA_KEY_INFO_SECURE |
5637 (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
5638 WPA_KEY_INFO_MIC : 0) |
5639 WPA_KEY_INFO_ACK |
5640 (!sm->Pair ? WPA_KEY_INFO_INSTALL : 0),
5641 rsc, NULL, kde, kde_len, gsm->GN, 1);
5642
5643 os_free(kde_buf);
5644 return 0;
5645}
5646
Roshan Pius3a1667e2018-07-03 15:17:14 -07005647
5648int wpa_auth_rekey_gtk(struct wpa_authenticator *wpa_auth)
5649{
5650 if (!wpa_auth)
5651 return -1;
5652 eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL);
5653 return eloop_register_timeout(0, 0, wpa_rekey_gtk, wpa_auth, NULL);
5654}
5655
Hai Shalomb755a2a2020-04-23 21:49:02 -07005656
Hai Shaloma20dcd72022-02-04 13:43:00 -08005657int wpa_auth_rekey_ptk(struct wpa_authenticator *wpa_auth,
5658 struct wpa_state_machine *sm)
5659{
5660 if (!wpa_auth || !sm)
5661 return -1;
5662 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "rekeying PTK");
5663 wpa_request_new_ptk(sm);
5664 wpa_sm_step(sm);
5665 return 0;
5666}
5667
5668
Hai Shalomb755a2a2020-04-23 21:49:02 -07005669void wpa_auth_set_ft_rsnxe_used(struct wpa_authenticator *wpa_auth, int val)
5670{
5671 if (wpa_auth)
5672 wpa_auth->conf.ft_rsnxe_used = val;
5673}
5674
Hai Shalom899fcc72020-10-19 14:38:18 -07005675
5676void wpa_auth_set_ocv_override_freq(struct wpa_authenticator *wpa_auth,
5677 enum wpa_auth_ocv_override_frame frame,
5678 unsigned int freq)
5679{
5680 if (!wpa_auth)
5681 return;
5682 switch (frame) {
5683 case WPA_AUTH_OCV_OVERRIDE_EAPOL_M3:
5684 wpa_auth->conf.oci_freq_override_eapol_m3 = freq;
5685 break;
5686 case WPA_AUTH_OCV_OVERRIDE_EAPOL_G1:
5687 wpa_auth->conf.oci_freq_override_eapol_g1 = freq;
5688 break;
5689 case WPA_AUTH_OCV_OVERRIDE_FT_ASSOC:
5690 wpa_auth->conf.oci_freq_override_ft_assoc = freq;
5691 break;
5692 case WPA_AUTH_OCV_OVERRIDE_FILS_ASSOC:
5693 wpa_auth->conf.oci_freq_override_fils_assoc = freq;
5694 break;
5695 }
5696}
5697
Kai Shie75b0652020-11-24 20:31:29 -08005698void wpa_auth_set_skip_send_eapol(struct wpa_authenticator *wpa_auth,
5699 u8 val)
5700{
5701 if (wpa_auth)
5702 wpa_auth->conf.skip_send_eapol = val;
5703}
5704
5705void wpa_auth_set_enable_eapol_large_timeout(struct wpa_authenticator *wpa_auth,
5706 u8 val)
5707{
5708 if (wpa_auth)
5709 wpa_auth->conf.enable_eapol_large_timeout = val;
5710}
5711
5712
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005713#endif /* CONFIG_TESTING_OPTIONS */