blob: 9d74bfcd78e24bf1aea2c0f9466763cf808fdbf9 [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;
Paul Stewart092955c2017-02-06 09:13:09 -0800191 return wpa_auth->cb->send_eapol(wpa_auth->cb_ctx, addr, data, data_len,
192 encrypt);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700193}
194
195
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800196#ifdef CONFIG_MESH
197static inline int wpa_auth_start_ampe(struct wpa_authenticator *wpa_auth,
198 const u8 *addr)
199{
Hai Shalomfdcde762020-04-02 11:19:20 -0700200 if (!wpa_auth->cb->start_ampe)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800201 return -1;
Paul Stewart092955c2017-02-06 09:13:09 -0800202 return wpa_auth->cb->start_ampe(wpa_auth->cb_ctx, addr);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800203}
204#endif /* CONFIG_MESH */
205
206
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700207int wpa_auth_for_each_sta(struct wpa_authenticator *wpa_auth,
208 int (*cb)(struct wpa_state_machine *sm, void *ctx),
209 void *cb_ctx)
210{
Hai Shalomfdcde762020-04-02 11:19:20 -0700211 if (!wpa_auth->cb->for_each_sta)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700212 return 0;
Paul Stewart092955c2017-02-06 09:13:09 -0800213 return wpa_auth->cb->for_each_sta(wpa_auth->cb_ctx, cb, cb_ctx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700214}
215
216
217int wpa_auth_for_each_auth(struct wpa_authenticator *wpa_auth,
218 int (*cb)(struct wpa_authenticator *a, void *ctx),
219 void *cb_ctx)
220{
Hai Shalomfdcde762020-04-02 11:19:20 -0700221 if (!wpa_auth->cb->for_each_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700222 return 0;
Paul Stewart092955c2017-02-06 09:13:09 -0800223 return wpa_auth->cb->for_each_auth(wpa_auth->cb_ctx, cb, cb_ctx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700224}
225
226
227void wpa_auth_logger(struct wpa_authenticator *wpa_auth, const u8 *addr,
228 logger_level level, const char *txt)
229{
Hai Shalomfdcde762020-04-02 11:19:20 -0700230 if (!wpa_auth->cb->logger)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700231 return;
Paul Stewart092955c2017-02-06 09:13:09 -0800232 wpa_auth->cb->logger(wpa_auth->cb_ctx, addr, level, txt);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700233}
234
235
236void wpa_auth_vlogger(struct wpa_authenticator *wpa_auth, const u8 *addr,
237 logger_level level, const char *fmt, ...)
238{
239 char *format;
240 int maxlen;
241 va_list ap;
242
Hai Shalomfdcde762020-04-02 11:19:20 -0700243 if (!wpa_auth->cb->logger)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700244 return;
245
246 maxlen = os_strlen(fmt) + 100;
247 format = os_malloc(maxlen);
248 if (!format)
249 return;
250
251 va_start(ap, fmt);
252 vsnprintf(format, maxlen, fmt, ap);
253 va_end(ap);
254
255 wpa_auth_logger(wpa_auth, addr, level, format);
256
257 os_free(format);
258}
259
260
261static void wpa_sta_disconnect(struct wpa_authenticator *wpa_auth,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700262 const u8 *addr, u16 reason)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700263{
Hai Shalomfdcde762020-04-02 11:19:20 -0700264 if (!wpa_auth->cb->disconnect)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700265 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700266 wpa_printf(MSG_DEBUG, "wpa_sta_disconnect STA " MACSTR " (reason %u)",
267 MAC2STR(addr), reason);
268 wpa_auth->cb->disconnect(wpa_auth->cb_ctx, addr, reason);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700269}
270
271
Hai Shalom74f70d42019-02-11 14:42:39 -0800272#ifdef CONFIG_OCV
273static int wpa_channel_info(struct wpa_authenticator *wpa_auth,
274 struct wpa_channel_info *ci)
275{
276 if (!wpa_auth->cb->channel_info)
277 return -1;
278 return wpa_auth->cb->channel_info(wpa_auth->cb_ctx, ci);
279}
280#endif /* CONFIG_OCV */
281
282
Hai Shalom021b0b52019-04-10 11:17:58 -0700283static int wpa_auth_update_vlan(struct wpa_authenticator *wpa_auth,
284 const u8 *addr, int vlan_id)
285{
286 if (!wpa_auth->cb->update_vlan)
287 return -1;
288 return wpa_auth->cb->update_vlan(wpa_auth->cb_ctx, addr, vlan_id);
289}
290
291
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700292static void wpa_rekey_gmk(void *eloop_ctx, void *timeout_ctx)
293{
294 struct wpa_authenticator *wpa_auth = eloop_ctx;
295
296 if (random_get_bytes(wpa_auth->group->GMK, WPA_GMK_LEN)) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700297 wpa_printf(MSG_ERROR,
298 "Failed to get random data for WPA initialization.");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700299 } else {
300 wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "GMK rekeyd");
301 wpa_hexdump_key(MSG_DEBUG, "GMK",
302 wpa_auth->group->GMK, WPA_GMK_LEN);
303 }
304
305 if (wpa_auth->conf.wpa_gmk_rekey) {
306 eloop_register_timeout(wpa_auth->conf.wpa_gmk_rekey, 0,
307 wpa_rekey_gmk, wpa_auth, NULL);
308 }
309}
310
311
312static void wpa_rekey_gtk(void *eloop_ctx, void *timeout_ctx)
313{
314 struct wpa_authenticator *wpa_auth = eloop_ctx;
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700315 struct wpa_group *group, *next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700316
317 wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "rekeying GTK");
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700318 group = wpa_auth->group;
319 while (group) {
320 wpa_group_get(wpa_auth, group);
321
Hai Shalome21d4e82020-04-29 16:34:06 -0700322 group->GTKReKey = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700323 do {
Hai Shalome21d4e82020-04-29 16:34:06 -0700324 group->changed = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700325 wpa_group_sm_step(wpa_auth, group);
326 } while (group->changed);
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700327
328 next = group->next;
329 wpa_group_put(wpa_auth, group);
330 group = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700331 }
332
333 if (wpa_auth->conf.wpa_group_rekey) {
334 eloop_register_timeout(wpa_auth->conf.wpa_group_rekey,
335 0, wpa_rekey_gtk, wpa_auth, NULL);
336 }
337}
338
339
340static void wpa_rekey_ptk(void *eloop_ctx, void *timeout_ctx)
341{
342 struct wpa_authenticator *wpa_auth = eloop_ctx;
343 struct wpa_state_machine *sm = timeout_ctx;
344
345 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "rekeying PTK");
346 wpa_request_new_ptk(sm);
347 wpa_sm_step(sm);
348}
349
350
Hai Shalom81f62d82019-07-22 12:10:00 -0700351void wpa_auth_set_ptk_rekey_timer(struct wpa_state_machine *sm)
352{
353 if (sm && sm->wpa_auth->conf.wpa_ptk_rekey) {
354 wpa_printf(MSG_DEBUG, "WPA: Start PTK rekeying timer for "
355 MACSTR " (%d seconds)", MAC2STR(sm->addr),
356 sm->wpa_auth->conf.wpa_ptk_rekey);
357 eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm);
358 eloop_register_timeout(sm->wpa_auth->conf.wpa_ptk_rekey, 0,
359 wpa_rekey_ptk, sm->wpa_auth, sm);
360 }
361}
362
363
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700364static int wpa_auth_pmksa_clear_cb(struct wpa_state_machine *sm, void *ctx)
365{
366 if (sm->pmksa == ctx)
367 sm->pmksa = NULL;
368 return 0;
369}
370
371
372static void wpa_auth_pmksa_free_cb(struct rsn_pmksa_cache_entry *entry,
373 void *ctx)
374{
375 struct wpa_authenticator *wpa_auth = ctx;
376 wpa_auth_for_each_sta(wpa_auth, wpa_auth_pmksa_clear_cb, entry);
377}
378
379
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700380static int wpa_group_init_gmk_and_counter(struct wpa_authenticator *wpa_auth,
381 struct wpa_group *group)
382{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800383 u8 buf[ETH_ALEN + 8 + sizeof(unsigned long)];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700384 u8 rkey[32];
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800385 unsigned long ptr;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700386
387 if (random_get_bytes(group->GMK, WPA_GMK_LEN) < 0)
388 return -1;
389 wpa_hexdump_key(MSG_DEBUG, "GMK", group->GMK, WPA_GMK_LEN);
390
391 /*
392 * Counter = PRF-256(Random number, "Init Counter",
393 * Local MAC Address || Time)
394 */
395 os_memcpy(buf, wpa_auth->addr, ETH_ALEN);
396 wpa_get_ntp_timestamp(buf + ETH_ALEN);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800397 ptr = (unsigned long) group;
398 os_memcpy(buf + ETH_ALEN + 8, &ptr, sizeof(ptr));
Hai Shalom74f70d42019-02-11 14:42:39 -0800399#ifdef TEST_FUZZ
400 os_memset(buf + ETH_ALEN, 0xab, 8);
401 os_memset(buf + ETH_ALEN + 8, 0xcd, sizeof(ptr));
402#endif /* TEST_FUZZ */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700403 if (random_get_bytes(rkey, sizeof(rkey)) < 0)
404 return -1;
405
406 if (sha1_prf(rkey, sizeof(rkey), "Init Counter", buf, sizeof(buf),
407 group->Counter, WPA_NONCE_LEN) < 0)
408 return -1;
409 wpa_hexdump_key(MSG_DEBUG, "Key Counter",
410 group->Counter, WPA_NONCE_LEN);
411
412 return 0;
413}
414
415
416static struct wpa_group * wpa_group_init(struct wpa_authenticator *wpa_auth,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800417 int vlan_id, int delay_init)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700418{
419 struct wpa_group *group;
420
421 group = os_zalloc(sizeof(struct wpa_group));
Hai Shalomfdcde762020-04-02 11:19:20 -0700422 if (!group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700423 return NULL;
424
Hai Shalome21d4e82020-04-29 16:34:06 -0700425 group->GTKAuthenticator = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700426 group->vlan_id = vlan_id;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -0700427 group->GTK_len = wpa_cipher_key_len(wpa_auth->conf.wpa_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700428
429 if (random_pool_ready() != 1) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700430 wpa_printf(MSG_INFO,
431 "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 -0700432 }
433
434 /*
435 * Set initial GMK/Counter value here. The actual values that will be
436 * used in negotiations will be set once the first station tries to
437 * connect. This allows more time for collecting additional randomness
438 * on embedded devices.
439 */
440 if (wpa_group_init_gmk_and_counter(wpa_auth, group) < 0) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700441 wpa_printf(MSG_ERROR,
442 "Failed to get random data for WPA initialization.");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700443 os_free(group);
444 return NULL;
445 }
446
Hai Shalome21d4e82020-04-29 16:34:06 -0700447 group->GInit = true;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800448 if (delay_init) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700449 wpa_printf(MSG_DEBUG,
450 "WPA: Delay group state machine start until Beacon frames have been configured");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800451 /* Initialization is completed in wpa_init_keys(). */
452 } else {
453 wpa_group_sm_step(wpa_auth, group);
Hai Shalome21d4e82020-04-29 16:34:06 -0700454 group->GInit = false;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800455 wpa_group_sm_step(wpa_auth, group);
456 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700457
458 return group;
459}
460
461
462/**
463 * wpa_init - Initialize WPA authenticator
464 * @addr: Authenticator address
465 * @conf: Configuration for WPA authenticator
466 * @cb: Callback functions for WPA authenticator
467 * Returns: Pointer to WPA authenticator data or %NULL on failure
468 */
469struct wpa_authenticator * wpa_init(const u8 *addr,
470 struct wpa_auth_config *conf,
Paul Stewart092955c2017-02-06 09:13:09 -0800471 const struct wpa_auth_callbacks *cb,
472 void *cb_ctx)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700473{
474 struct wpa_authenticator *wpa_auth;
475
476 wpa_auth = os_zalloc(sizeof(struct wpa_authenticator));
Hai Shalomfdcde762020-04-02 11:19:20 -0700477 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700478 return NULL;
479 os_memcpy(wpa_auth->addr, addr, ETH_ALEN);
480 os_memcpy(&wpa_auth->conf, conf, sizeof(*conf));
Paul Stewart092955c2017-02-06 09:13:09 -0800481 wpa_auth->cb = cb;
482 wpa_auth->cb_ctx = cb_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700483
484 if (wpa_auth_gen_wpa_ie(wpa_auth)) {
485 wpa_printf(MSG_ERROR, "Could not generate WPA IE.");
486 os_free(wpa_auth);
487 return NULL;
488 }
489
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800490 wpa_auth->group = wpa_group_init(wpa_auth, 0, 1);
Hai Shalomfdcde762020-04-02 11:19:20 -0700491 if (!wpa_auth->group) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700492 os_free(wpa_auth->wpa_ie);
493 os_free(wpa_auth);
494 return NULL;
495 }
496
497 wpa_auth->pmksa = pmksa_cache_auth_init(wpa_auth_pmksa_free_cb,
498 wpa_auth);
Hai Shalomfdcde762020-04-02 11:19:20 -0700499 if (!wpa_auth->pmksa) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700500 wpa_printf(MSG_ERROR, "PMKSA cache initialization failed.");
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800501 os_free(wpa_auth->group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700502 os_free(wpa_auth->wpa_ie);
503 os_free(wpa_auth);
504 return NULL;
505 }
506
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800507#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700508 wpa_auth->ft_pmk_cache = wpa_ft_pmk_cache_init();
Hai Shalomfdcde762020-04-02 11:19:20 -0700509 if (!wpa_auth->ft_pmk_cache) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700510 wpa_printf(MSG_ERROR, "FT PMK cache initialization failed.");
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800511 os_free(wpa_auth->group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700512 os_free(wpa_auth->wpa_ie);
513 pmksa_cache_auth_deinit(wpa_auth->pmksa);
514 os_free(wpa_auth);
515 return NULL;
516 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800517#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700518
519 if (wpa_auth->conf.wpa_gmk_rekey) {
520 eloop_register_timeout(wpa_auth->conf.wpa_gmk_rekey, 0,
521 wpa_rekey_gmk, wpa_auth, NULL);
522 }
523
524 if (wpa_auth->conf.wpa_group_rekey) {
525 eloop_register_timeout(wpa_auth->conf.wpa_group_rekey, 0,
526 wpa_rekey_gtk, wpa_auth, NULL);
527 }
528
Dmitry Shmidtcf32e602014-01-28 10:57:39 -0800529#ifdef CONFIG_P2P
530 if (WPA_GET_BE32(conf->ip_addr_start)) {
531 int count = WPA_GET_BE32(conf->ip_addr_end) -
532 WPA_GET_BE32(conf->ip_addr_start) + 1;
533 if (count > 1000)
534 count = 1000;
535 if (count > 0)
536 wpa_auth->ip_pool = bitfield_alloc(count);
537 }
538#endif /* CONFIG_P2P */
539
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700540 return wpa_auth;
541}
542
543
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800544int wpa_init_keys(struct wpa_authenticator *wpa_auth)
545{
546 struct wpa_group *group = wpa_auth->group;
547
Hai Shalomfdcde762020-04-02 11:19:20 -0700548 wpa_printf(MSG_DEBUG,
549 "WPA: Start group state machine to set initial keys");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800550 wpa_group_sm_step(wpa_auth, group);
Hai Shalome21d4e82020-04-29 16:34:06 -0700551 group->GInit = false;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800552 wpa_group_sm_step(wpa_auth, group);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800553 if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
554 return -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800555 return 0;
556}
557
558
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700559/**
560 * wpa_deinit - Deinitialize WPA authenticator
561 * @wpa_auth: Pointer to WPA authenticator data from wpa_init()
562 */
563void wpa_deinit(struct wpa_authenticator *wpa_auth)
564{
565 struct wpa_group *group, *prev;
566
567 eloop_cancel_timeout(wpa_rekey_gmk, wpa_auth, NULL);
568 eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL);
569
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700570 pmksa_cache_auth_deinit(wpa_auth->pmksa);
571
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800572#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700573 wpa_ft_pmk_cache_deinit(wpa_auth->ft_pmk_cache);
574 wpa_auth->ft_pmk_cache = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700575 wpa_ft_deinit(wpa_auth);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800576#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700577
Dmitry Shmidtcf32e602014-01-28 10:57:39 -0800578#ifdef CONFIG_P2P
579 bitfield_free(wpa_auth->ip_pool);
580#endif /* CONFIG_P2P */
581
582
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700583 os_free(wpa_auth->wpa_ie);
584
585 group = wpa_auth->group;
586 while (group) {
587 prev = group;
588 group = group->next;
589 os_free(prev);
590 }
591
592 os_free(wpa_auth);
593}
594
595
596/**
597 * wpa_reconfig - Update WPA authenticator configuration
598 * @wpa_auth: Pointer to WPA authenticator data from wpa_init()
599 * @conf: Configuration for WPA authenticator
600 */
601int wpa_reconfig(struct wpa_authenticator *wpa_auth,
602 struct wpa_auth_config *conf)
603{
604 struct wpa_group *group;
Hai Shalomfdcde762020-04-02 11:19:20 -0700605
606 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700607 return 0;
608
609 os_memcpy(&wpa_auth->conf, conf, sizeof(*conf));
610 if (wpa_auth_gen_wpa_ie(wpa_auth)) {
611 wpa_printf(MSG_ERROR, "Could not generate WPA IE.");
612 return -1;
613 }
614
615 /*
616 * Reinitialize GTK to make sure it is suitable for the new
617 * configuration.
618 */
619 group = wpa_auth->group;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -0700620 group->GTK_len = wpa_cipher_key_len(wpa_auth->conf.wpa_group);
Hai Shalome21d4e82020-04-29 16:34:06 -0700621 group->GInit = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700622 wpa_group_sm_step(wpa_auth, group);
Hai Shalome21d4e82020-04-29 16:34:06 -0700623 group->GInit = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700624 wpa_group_sm_step(wpa_auth, group);
625
626 return 0;
627}
628
629
630struct wpa_state_machine *
Dmitry Shmidt391c59f2013-09-03 12:16:28 -0700631wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr,
632 const u8 *p2p_dev_addr)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700633{
634 struct wpa_state_machine *sm;
635
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800636 if (wpa_auth->group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
637 return NULL;
638
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700639 sm = os_zalloc(sizeof(struct wpa_state_machine));
Hai Shalomfdcde762020-04-02 11:19:20 -0700640 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700641 return NULL;
642 os_memcpy(sm->addr, addr, ETH_ALEN);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -0700643 if (p2p_dev_addr)
644 os_memcpy(sm->p2p_dev_addr, p2p_dev_addr, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700645
646 sm->wpa_auth = wpa_auth;
647 sm->group = wpa_auth->group;
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700648 wpa_group_get(sm->wpa_auth, sm->group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700649
650 return sm;
651}
652
653
654int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth,
655 struct wpa_state_machine *sm)
656{
Hai Shalomfdcde762020-04-02 11:19:20 -0700657 if (!wpa_auth || !wpa_auth->conf.wpa || !sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700658 return -1;
659
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800660#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700661 if (sm->ft_completed) {
662 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -0700663 "FT authentication already completed - do not start 4-way handshake");
Dmitry Shmidt71757432014-06-02 13:50:35 -0700664 /* Go to PTKINITDONE state to allow GTK rekeying */
665 sm->wpa_ptk_state = WPA_PTK_PTKINITDONE;
Hai Shalome21d4e82020-04-29 16:34:06 -0700666 sm->Pair = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700667 return 0;
668 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800669#endif /* CONFIG_IEEE80211R_AP */
670
671#ifdef CONFIG_FILS
672 if (sm->fils_completed) {
673 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
674 "FILS authentication already completed - do not start 4-way handshake");
675 /* Go to PTKINITDONE state to allow GTK rekeying */
676 sm->wpa_ptk_state = WPA_PTK_PTKINITDONE;
Hai Shalome21d4e82020-04-29 16:34:06 -0700677 sm->Pair = true;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800678 return 0;
679 }
680#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700681
682 if (sm->started) {
683 os_memset(&sm->key_replay, 0, sizeof(sm->key_replay));
Hai Shalome21d4e82020-04-29 16:34:06 -0700684 sm->ReAuthenticationRequest = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700685 return wpa_sm_step(sm);
686 }
687
688 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
689 "start authentication");
690 sm->started = 1;
691
Hai Shalome21d4e82020-04-29 16:34:06 -0700692 sm->Init = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700693 if (wpa_sm_step(sm) == 1)
694 return 1; /* should not really happen */
Hai Shalome21d4e82020-04-29 16:34:06 -0700695 sm->Init = false;
696 sm->AuthenticationRequest = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700697 return wpa_sm_step(sm);
698}
699
700
701void wpa_auth_sta_no_wpa(struct wpa_state_machine *sm)
702{
703 /* WPA/RSN was not used - clear WPA state. This is needed if the STA
704 * reassociates back to the same AP while the previous entry for the
705 * STA has not yet been removed. */
Hai Shalomfdcde762020-04-02 11:19:20 -0700706 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700707 return;
708
709 sm->wpa_key_mgmt = 0;
710}
711
712
713static void wpa_free_sta_sm(struct wpa_state_machine *sm)
714{
Dmitry Shmidtcf32e602014-01-28 10:57:39 -0800715#ifdef CONFIG_P2P
716 if (WPA_GET_BE32(sm->ip_addr)) {
717 u32 start;
Hai Shalomfdcde762020-04-02 11:19:20 -0700718 wpa_printf(MSG_DEBUG,
719 "P2P: Free assigned IP address %u.%u.%u.%u from "
720 MACSTR,
Dmitry Shmidtcf32e602014-01-28 10:57:39 -0800721 sm->ip_addr[0], sm->ip_addr[1],
722 sm->ip_addr[2], sm->ip_addr[3],
723 MAC2STR(sm->addr));
724 start = WPA_GET_BE32(sm->wpa_auth->conf.ip_addr_start);
725 bitfield_clear(sm->wpa_auth->ip_pool,
726 WPA_GET_BE32(sm->ip_addr) - start);
727 }
728#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700729 if (sm->GUpdateStationKeys) {
730 sm->group->GKeyDoneStations--;
Hai Shalome21d4e82020-04-29 16:34:06 -0700731 sm->GUpdateStationKeys = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700732 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800733#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700734 os_free(sm->assoc_resp_ftie);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700735 wpabuf_free(sm->ft_pending_req_ies);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800736#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700737 os_free(sm->last_rx_eapol_key);
738 os_free(sm->wpa_ie);
Hai Shalomc3565922019-10-28 11:58:20 -0700739 os_free(sm->rsnxe);
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700740 wpa_group_put(sm->wpa_auth, sm->group);
Hai Shalom021b0b52019-04-10 11:17:58 -0700741#ifdef CONFIG_DPP2
742 wpabuf_clear_free(sm->dpp_z);
743#endif /* CONFIG_DPP2 */
Hai Shalom1dc4d202019-04-29 16:22:27 -0700744 bin_clear_free(sm, sizeof(*sm));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700745}
746
747
748void wpa_auth_sta_deinit(struct wpa_state_machine *sm)
749{
Hai Shalomfdcde762020-04-02 11:19:20 -0700750 struct wpa_authenticator *wpa_auth;
751
752 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700753 return;
754
Hai Shalomfdcde762020-04-02 11:19:20 -0700755 wpa_auth = sm->wpa_auth;
756 if (wpa_auth->conf.wpa_strict_rekey && sm->has_GTK) {
757 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
758 "strict rekeying - force GTK rekey since STA is leaving");
Roshan Pius3a1667e2018-07-03 15:17:14 -0700759 if (eloop_deplete_timeout(0, 500000, wpa_rekey_gtk,
Hai Shalomfdcde762020-04-02 11:19:20 -0700760 wpa_auth, NULL) == -1)
761 eloop_register_timeout(0, 500000, wpa_rekey_gtk,
762 wpa_auth, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700763 }
764
Hai Shalomfdcde762020-04-02 11:19:20 -0700765 eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700766 sm->pending_1_of_4_timeout = 0;
767 eloop_cancel_timeout(wpa_sm_call_step, sm, NULL);
Hai Shalomfdcde762020-04-02 11:19:20 -0700768 eloop_cancel_timeout(wpa_rekey_ptk, wpa_auth, sm);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700769#ifdef CONFIG_IEEE80211R_AP
770 wpa_ft_sta_deinit(sm);
771#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700772 if (sm->in_step_loop) {
773 /* Must not free state machine while wpa_sm_step() is running.
774 * Freeing will be completed in the end of wpa_sm_step(). */
Hai Shalomfdcde762020-04-02 11:19:20 -0700775 wpa_printf(MSG_DEBUG,
776 "WPA: Registering pending STA state machine deinit for "
777 MACSTR, MAC2STR(sm->addr));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700778 sm->pending_deinit = 1;
779 } else
780 wpa_free_sta_sm(sm);
781}
782
783
784static void wpa_request_new_ptk(struct wpa_state_machine *sm)
785{
Hai Shalomfdcde762020-04-02 11:19:20 -0700786 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700787 return;
788
Hai Shalomfdcde762020-04-02 11:19:20 -0700789 if (!sm->use_ext_key_id && sm->wpa_auth->conf.wpa_deny_ptk0_rekey) {
790 wpa_printf(MSG_INFO,
791 "WPA: PTK0 rekey not allowed, disconnect " MACSTR,
792 MAC2STR(sm->addr));
Hai Shalome21d4e82020-04-29 16:34:06 -0700793 sm->Disconnect = true;
Hai Shalomfdcde762020-04-02 11:19:20 -0700794 /* Try to encourage the STA to reconnect */
795 sm->disconnect_reason =
796 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA;
797 } else {
798 if (sm->use_ext_key_id)
799 sm->keyidx_active ^= 1; /* flip Key ID */
Hai Shalome21d4e82020-04-29 16:34:06 -0700800 sm->PTKRequest = true;
Hai Shalomfdcde762020-04-02 11:19:20 -0700801 sm->PTK_valid = 0;
802 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700803}
804
805
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800806static int wpa_replay_counter_valid(struct wpa_key_replay_counter *ctr,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700807 const u8 *replay_counter)
808{
809 int i;
810 for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800811 if (!ctr[i].valid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700812 break;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800813 if (os_memcmp(replay_counter, ctr[i].counter,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700814 WPA_REPLAY_COUNTER_LEN) == 0)
815 return 1;
816 }
817 return 0;
818}
819
820
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800821static void wpa_replay_counter_mark_invalid(struct wpa_key_replay_counter *ctr,
822 const u8 *replay_counter)
823{
824 int i;
825 for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) {
826 if (ctr[i].valid &&
Hai Shalomfdcde762020-04-02 11:19:20 -0700827 (!replay_counter ||
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800828 os_memcmp(replay_counter, ctr[i].counter,
829 WPA_REPLAY_COUNTER_LEN) == 0))
Hai Shalome21d4e82020-04-29 16:34:06 -0700830 ctr[i].valid = false;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800831 }
832}
833
834
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800835#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700836static int ft_check_msg_2_of_4(struct wpa_authenticator *wpa_auth,
837 struct wpa_state_machine *sm,
838 struct wpa_eapol_ie_parse *kde)
839{
840 struct wpa_ie_data ie;
841 struct rsn_mdie *mdie;
842
843 if (wpa_parse_wpa_ie_rsn(kde->rsn_ie, kde->rsn_ie_len, &ie) < 0 ||
Hai Shalomfdcde762020-04-02 11:19:20 -0700844 ie.num_pmkid != 1 || !ie.pmkid) {
845 wpa_printf(MSG_DEBUG,
846 "FT: No PMKR1Name in FT 4-way handshake message 2/4");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700847 return -1;
848 }
849
850 os_memcpy(sm->sup_pmk_r1_name, ie.pmkid, PMKID_LEN);
851 wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from Supplicant",
852 sm->sup_pmk_r1_name, PMKID_LEN);
853
854 if (!kde->mdie || !kde->ftie) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700855 wpa_printf(MSG_DEBUG,
856 "FT: No %s in FT 4-way handshake message 2/4",
857 kde->mdie ? "FTIE" : "MDIE");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700858 return -1;
859 }
860
861 mdie = (struct rsn_mdie *) (kde->mdie + 2);
862 if (kde->mdie[1] < sizeof(struct rsn_mdie) ||
863 os_memcmp(wpa_auth->conf.mobility_domain, mdie->mobility_domain,
864 MOBILITY_DOMAIN_ID_LEN) != 0) {
865 wpa_printf(MSG_DEBUG, "FT: MDIE mismatch");
866 return -1;
867 }
868
869 if (sm->assoc_resp_ftie &&
870 (kde->ftie[1] != sm->assoc_resp_ftie[1] ||
871 os_memcmp(kde->ftie, sm->assoc_resp_ftie,
872 2 + sm->assoc_resp_ftie[1]) != 0)) {
873 wpa_printf(MSG_DEBUG, "FT: FTIE mismatch");
874 wpa_hexdump(MSG_DEBUG, "FT: FTIE in EAPOL-Key msg 2/4",
875 kde->ftie, kde->ftie_len);
876 wpa_hexdump(MSG_DEBUG, "FT: FTIE in (Re)AssocResp",
877 sm->assoc_resp_ftie, 2 + sm->assoc_resp_ftie[1]);
878 return -1;
879 }
880
881 return 0;
882}
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800883#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700884
885
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800886static int wpa_receive_error_report(struct wpa_authenticator *wpa_auth,
887 struct wpa_state_machine *sm, int group)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800888{
889 /* Supplicant reported a Michael MIC error */
890 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -0700891 "received EAPOL-Key Error Request (STA detected Michael MIC failure (group=%d))",
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800892 group);
893
894 if (group && wpa_auth->conf.wpa_group != WPA_CIPHER_TKIP) {
895 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -0700896 "ignore Michael MIC failure report since group cipher is not TKIP");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800897 } else if (!group && sm->pairwise != WPA_CIPHER_TKIP) {
898 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -0700899 "ignore Michael MIC failure report since pairwise cipher is not TKIP");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800900 } else {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800901 if (wpa_auth_mic_failure_report(wpa_auth, sm->addr) > 0)
902 return 1; /* STA entry was removed */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800903 sm->dot11RSNAStatsTKIPRemoteMICFailures++;
904 wpa_auth->dot11RSNAStatsTKIPRemoteMICFailures++;
905 }
906
907 /*
908 * Error report is not a request for a new key handshake, but since
909 * Authenticator may do it, let's change the keys now anyway.
910 */
911 wpa_request_new_ptk(sm);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800912 return 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800913}
914
915
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800916static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data,
917 size_t data_len)
918{
919 struct wpa_ptk PTK;
920 int ok = 0;
921 const u8 *pmk = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700922 size_t pmk_len;
Hai Shalom021b0b52019-04-10 11:17:58 -0700923 int vlan_id = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800924
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800925 os_memset(&PTK, 0, sizeof(PTK));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800926 for (;;) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700927 if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
928 !wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800929 pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr,
Hai Shalom021b0b52019-04-10 11:17:58 -0700930 sm->p2p_dev_addr, pmk, &pmk_len,
931 &vlan_id);
Hai Shalomfdcde762020-04-02 11:19:20 -0700932 if (!pmk)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800933 break;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700934#ifdef CONFIG_IEEE80211R_AP
935 if (wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) {
936 os_memcpy(sm->xxkey, pmk, pmk_len);
937 sm->xxkey_len = pmk_len;
938 }
939#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800940 } else {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800941 pmk = sm->PMK;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800942 pmk_len = sm->pmk_len;
943 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800944
Hai Shalomfdcde762020-04-02 11:19:20 -0700945 if (wpa_derive_ptk(sm, sm->alt_SNonce, pmk, pmk_len, &PTK, 0) <
946 0)
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800947 break;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800948
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700949 if (wpa_verify_key_mic(sm->wpa_key_mgmt, pmk_len, &PTK,
950 data, data_len) == 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -0700951 if (sm->PMK != pmk) {
952 os_memcpy(sm->PMK, pmk, pmk_len);
953 sm->pmk_len = pmk_len;
954 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800955 ok = 1;
956 break;
957 }
958
Roshan Pius3a1667e2018-07-03 15:17:14 -0700959 if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
960 wpa_key_mgmt_sae(sm->wpa_key_mgmt))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800961 break;
962 }
963
964 if (!ok) {
965 wpa_printf(MSG_DEBUG,
966 "WPA: Earlier SNonce did not result in matching MIC");
967 return -1;
968 }
969
970 wpa_printf(MSG_DEBUG,
971 "WPA: Earlier SNonce resulted in matching MIC");
972 sm->alt_snonce_valid = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -0700973
974 if (vlan_id && wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
975 wpa_auth_update_vlan(sm->wpa_auth, sm->addr, vlan_id) < 0)
976 return -1;
977
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800978 os_memcpy(sm->SNonce, sm->alt_SNonce, WPA_NONCE_LEN);
979 os_memcpy(&sm->PTK, &PTK, sizeof(PTK));
Hai Shalom81f62d82019-07-22 12:10:00 -0700980 forced_memzero(&PTK, sizeof(PTK));
Hai Shalome21d4e82020-04-29 16:34:06 -0700981 sm->PTK_valid = true;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800982
983 return 0;
984}
985
986
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700987void wpa_receive(struct wpa_authenticator *wpa_auth,
988 struct wpa_state_machine *sm,
989 u8 *data, size_t data_len)
990{
991 struct ieee802_1x_hdr *hdr;
992 struct wpa_eapol_key *key;
993 u16 key_info, key_data_length;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700994 enum { PAIRWISE_2, PAIRWISE_4, GROUP_2, REQUEST } msg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700995 char *msgtxt;
996 struct wpa_eapol_ie_parse kde;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800997 const u8 *key_data;
998 size_t keyhdrlen, mic_len;
999 u8 *mic;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001000
Hai Shalomfdcde762020-04-02 11:19:20 -07001001 if (!wpa_auth || !wpa_auth->conf.wpa || !sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001002 return;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001003 wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL data", data, data_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001004
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001005 mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001006 keyhdrlen = sizeof(*key) + mic_len + 2;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001007
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001008 if (data_len < sizeof(*hdr) + keyhdrlen) {
1009 wpa_printf(MSG_DEBUG, "WPA: Ignore too short EAPOL-Key frame");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001010 return;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001011 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001012
1013 hdr = (struct ieee802_1x_hdr *) data;
1014 key = (struct wpa_eapol_key *) (hdr + 1);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001015 mic = (u8 *) (key + 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001016 key_info = WPA_GET_BE16(key->key_info);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001017 key_data = mic + mic_len + 2;
1018 key_data_length = WPA_GET_BE16(mic + mic_len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001019 wpa_printf(MSG_DEBUG, "WPA: Received EAPOL-Key from " MACSTR
Hai Shalomfdcde762020-04-02 11:19:20 -07001020 " key_info=0x%x type=%u mic_len=%zu key_data_length=%u",
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001021 MAC2STR(sm->addr), key_info, key->type,
Hai Shalomfdcde762020-04-02 11:19:20 -07001022 mic_len, key_data_length);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001023 wpa_hexdump(MSG_MSGDUMP,
1024 "WPA: EAPOL-Key header (ending before Key MIC)",
1025 key, sizeof(*key));
1026 wpa_hexdump(MSG_MSGDUMP, "WPA: EAPOL-Key Key MIC",
1027 mic, mic_len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001028 if (key_data_length > data_len - sizeof(*hdr) - keyhdrlen) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001029 wpa_printf(MSG_INFO,
1030 "WPA: Invalid EAPOL-Key frame - key_data overflow (%d > %zu)",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001031 key_data_length,
Hai Shalomfdcde762020-04-02 11:19:20 -07001032 data_len - sizeof(*hdr) - keyhdrlen);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001033 return;
1034 }
1035
1036 if (sm->wpa == WPA_VERSION_WPA2) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001037 if (key->type == EAPOL_KEY_TYPE_WPA) {
1038 /*
1039 * Some deployed station implementations seem to send
1040 * msg 4/4 with incorrect type value in WPA2 mode.
1041 */
Hai Shalomfdcde762020-04-02 11:19:20 -07001042 wpa_printf(MSG_DEBUG,
1043 "Workaround: Allow EAPOL-Key with unexpected WPA type in RSN mode");
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001044 } else if (key->type != EAPOL_KEY_TYPE_RSN) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001045 wpa_printf(MSG_DEBUG,
1046 "Ignore EAPOL-Key with unexpected type %d in RSN mode",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001047 key->type);
1048 return;
1049 }
1050 } else {
1051 if (key->type != EAPOL_KEY_TYPE_WPA) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001052 wpa_printf(MSG_DEBUG,
1053 "Ignore EAPOL-Key with unexpected type %d in WPA mode",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001054 key->type);
1055 return;
1056 }
1057 }
1058
1059 wpa_hexdump(MSG_DEBUG, "WPA: Received Key Nonce", key->key_nonce,
1060 WPA_NONCE_LEN);
1061 wpa_hexdump(MSG_DEBUG, "WPA: Received Replay Counter",
1062 key->replay_counter, WPA_REPLAY_COUNTER_LEN);
1063
1064 /* FIX: verify that the EAPOL-Key frame was encrypted if pairwise keys
1065 * are set */
1066
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001067 if (key_info & WPA_KEY_INFO_SMK_MESSAGE) {
1068 wpa_printf(MSG_DEBUG, "WPA: Ignore SMK message");
1069 return;
1070 }
1071
1072 if (key_info & WPA_KEY_INFO_REQUEST) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001073 msg = REQUEST;
1074 msgtxt = "Request";
1075 } else if (!(key_info & WPA_KEY_INFO_KEY_TYPE)) {
1076 msg = GROUP_2;
1077 msgtxt = "2/2 Group";
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001078 } else if (key_data_length == 0 ||
1079 (mic_len == 0 && (key_info & WPA_KEY_INFO_ENCR_KEY_DATA) &&
1080 key_data_length == AES_BLOCK_SIZE)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001081 msg = PAIRWISE_4;
1082 msgtxt = "4/4 Pairwise";
1083 } else {
1084 msg = PAIRWISE_2;
1085 msgtxt = "2/4 Pairwise";
1086 }
1087
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001088 if (msg == REQUEST || msg == PAIRWISE_2 || msg == PAIRWISE_4 ||
1089 msg == GROUP_2) {
1090 u16 ver = key_info & WPA_KEY_INFO_TYPE_MASK;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001091 if (sm->pairwise == WPA_CIPHER_CCMP ||
1092 sm->pairwise == WPA_CIPHER_GCMP) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001093 if (wpa_use_cmac(sm->wpa_key_mgmt) &&
1094 !wpa_use_akm_defined(sm->wpa_key_mgmt) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001095 ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) {
1096 wpa_auth_logger(wpa_auth, sm->addr,
1097 LOGGER_WARNING,
Hai Shalomfdcde762020-04-02 11:19:20 -07001098 "advertised support for AES-128-CMAC, but did not use it");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001099 return;
1100 }
1101
Roshan Pius3a1667e2018-07-03 15:17:14 -07001102 if (!wpa_use_cmac(sm->wpa_key_mgmt) &&
1103 !wpa_use_akm_defined(sm->wpa_key_mgmt) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001104 ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
1105 wpa_auth_logger(wpa_auth, sm->addr,
1106 LOGGER_WARNING,
Hai Shalomfdcde762020-04-02 11:19:20 -07001107 "did not use HMAC-SHA1-AES with CCMP/GCMP");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001108 return;
1109 }
1110 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001111
Roshan Pius3a1667e2018-07-03 15:17:14 -07001112 if (wpa_use_akm_defined(sm->wpa_key_mgmt) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001113 ver != WPA_KEY_INFO_TYPE_AKM_DEFINED) {
1114 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING,
1115 "did not use EAPOL-Key descriptor version 0 as required for AKM-defined cases");
1116 return;
1117 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001118 }
1119
1120 if (key_info & WPA_KEY_INFO_REQUEST) {
1121 if (sm->req_replay_counter_used &&
1122 os_memcmp(key->replay_counter, sm->req_replay_counter,
1123 WPA_REPLAY_COUNTER_LEN) <= 0) {
1124 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING,
Hai Shalomfdcde762020-04-02 11:19:20 -07001125 "received EAPOL-Key request with replayed counter");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001126 return;
1127 }
1128 }
1129
1130 if (!(key_info & WPA_KEY_INFO_REQUEST) &&
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001131 !wpa_replay_counter_valid(sm->key_replay, key->replay_counter)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001132 int i;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001133
1134 if (msg == PAIRWISE_2 &&
1135 wpa_replay_counter_valid(sm->prev_key_replay,
1136 key->replay_counter) &&
1137 sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING &&
1138 os_memcmp(sm->SNonce, key->key_nonce, WPA_NONCE_LEN) != 0)
1139 {
1140 /*
1141 * Some supplicant implementations (e.g., Windows XP
1142 * WZC) update SNonce for each EAPOL-Key 2/4. This
1143 * breaks the workaround on accepting any of the
1144 * pending requests, so allow the SNonce to be updated
1145 * even if we have already sent out EAPOL-Key 3/4.
1146 */
1147 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07001148 "Process SNonce update from STA based on retransmitted EAPOL-Key 1/4");
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001149 sm->update_snonce = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001150 os_memcpy(sm->alt_SNonce, sm->SNonce, WPA_NONCE_LEN);
Hai Shalome21d4e82020-04-29 16:34:06 -07001151 sm->alt_snonce_valid = true;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001152 os_memcpy(sm->alt_replay_counter,
1153 sm->key_replay[0].counter,
1154 WPA_REPLAY_COUNTER_LEN);
1155 goto continue_processing;
1156 }
1157
1158 if (msg == PAIRWISE_4 && sm->alt_snonce_valid &&
1159 sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING &&
1160 os_memcmp(key->replay_counter, sm->alt_replay_counter,
1161 WPA_REPLAY_COUNTER_LEN) == 0) {
1162 /*
1163 * Supplicant may still be using the old SNonce since
1164 * there was two EAPOL-Key 2/4 messages and they had
1165 * different SNonce values.
1166 */
1167 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
1168 "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 -08001169 goto continue_processing;
1170 }
1171
1172 if (msg == PAIRWISE_2 &&
1173 wpa_replay_counter_valid(sm->prev_key_replay,
1174 key->replay_counter) &&
1175 sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING) {
1176 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07001177 "ignore retransmitted EAPOL-Key %s - SNonce did not change",
1178 msgtxt);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001179 } else {
1180 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07001181 "received EAPOL-Key %s with unexpected replay counter",
1182 msgtxt);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001183 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001184 for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) {
1185 if (!sm->key_replay[i].valid)
1186 break;
1187 wpa_hexdump(MSG_DEBUG, "pending replay counter",
1188 sm->key_replay[i].counter,
1189 WPA_REPLAY_COUNTER_LEN);
1190 }
1191 wpa_hexdump(MSG_DEBUG, "received replay counter",
1192 key->replay_counter, WPA_REPLAY_COUNTER_LEN);
1193 return;
1194 }
1195
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001196continue_processing:
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001197#ifdef CONFIG_FILS
1198 if (sm->wpa == WPA_VERSION_WPA2 && mic_len == 0 &&
1199 !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
1200 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
1201 "WPA: Encr Key Data bit not set even though AEAD cipher is supposed to be used - drop frame");
1202 return;
1203 }
1204#endif /* CONFIG_FILS */
1205
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001206 switch (msg) {
1207 case PAIRWISE_2:
1208 if (sm->wpa_ptk_state != WPA_PTK_PTKSTART &&
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001209 sm->wpa_ptk_state != WPA_PTK_PTKCALCNEGOTIATING &&
1210 (!sm->update_snonce ||
1211 sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001212 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001213 "received EAPOL-Key msg 2/4 in invalid state (%d) - dropped",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001214 sm->wpa_ptk_state);
1215 return;
1216 }
1217 random_add_randomness(key->key_nonce, WPA_NONCE_LEN);
1218 if (sm->group->reject_4way_hs_for_entropy) {
1219 /*
1220 * The system did not have enough entropy to generate
1221 * strong random numbers. Reject the first 4-way
1222 * handshake(s) and collect some entropy based on the
1223 * information from it. Once enough entropy is
1224 * available, the next atempt will trigger GMK/Key
1225 * Counter update and the station will be allowed to
1226 * continue.
1227 */
Hai Shalomfdcde762020-04-02 11:19:20 -07001228 wpa_printf(MSG_DEBUG,
1229 "WPA: Reject 4-way handshake to collect more entropy for random number generation");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001230 random_mark_pool_ready();
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001231 wpa_sta_disconnect(wpa_auth, sm->addr,
1232 WLAN_REASON_PREV_AUTH_NOT_VALID);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001233 return;
1234 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001235 break;
1236 case PAIRWISE_4:
1237 if (sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING ||
1238 !sm->PTK_valid) {
1239 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001240 "received EAPOL-Key msg 4/4 in invalid state (%d) - dropped",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001241 sm->wpa_ptk_state);
1242 return;
1243 }
1244 break;
1245 case GROUP_2:
1246 if (sm->wpa_ptk_group_state != WPA_PTK_GROUP_REKEYNEGOTIATING
1247 || !sm->PTK_valid) {
1248 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001249 "received EAPOL-Key msg 2/2 in invalid state (%d) - dropped",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001250 sm->wpa_ptk_group_state);
1251 return;
1252 }
1253 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001254 case REQUEST:
1255 break;
1256 }
1257
1258 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
1259 "received EAPOL-Key frame (%s)", msgtxt);
1260
1261 if (key_info & WPA_KEY_INFO_ACK) {
1262 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
1263 "received invalid EAPOL-Key: Key Ack set");
1264 return;
1265 }
1266
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001267 if (!wpa_key_mgmt_fils(sm->wpa_key_mgmt) &&
1268 !(key_info & WPA_KEY_INFO_MIC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001269 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
1270 "received invalid EAPOL-Key: Key MIC not set");
1271 return;
1272 }
1273
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001274#ifdef CONFIG_FILS
1275 if (wpa_key_mgmt_fils(sm->wpa_key_mgmt) &&
1276 (key_info & WPA_KEY_INFO_MIC)) {
1277 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
1278 "received invalid EAPOL-Key: Key MIC set");
1279 return;
1280 }
1281#endif /* CONFIG_FILS */
1282
Hai Shalome21d4e82020-04-29 16:34:06 -07001283 sm->MICVerified = false;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001284 if (sm->PTK_valid && !sm->update_snonce) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001285 if (mic_len &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001286 wpa_verify_key_mic(sm->wpa_key_mgmt, sm->pmk_len, &sm->PTK,
1287 data, data_len) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001288 (msg != PAIRWISE_4 || !sm->alt_snonce_valid ||
1289 wpa_try_alt_snonce(sm, data, data_len))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001290 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
1291 "received EAPOL-Key with invalid MIC");
Hai Shalom74f70d42019-02-11 14:42:39 -08001292#ifdef TEST_FUZZ
1293 wpa_printf(MSG_INFO,
1294 "TEST: Ignore Key MIC failure for fuzz testing");
1295 goto continue_fuzz;
1296#endif /* TEST_FUZZ */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001297 return;
1298 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001299#ifdef CONFIG_FILS
1300 if (!mic_len &&
1301 wpa_aead_decrypt(sm, &sm->PTK, data, data_len,
1302 &key_data_length) < 0) {
1303 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
1304 "received EAPOL-Key with invalid MIC");
Hai Shalom74f70d42019-02-11 14:42:39 -08001305#ifdef TEST_FUZZ
1306 wpa_printf(MSG_INFO,
1307 "TEST: Ignore Key MIC failure for fuzz testing");
1308 goto continue_fuzz;
1309#endif /* TEST_FUZZ */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001310 return;
1311 }
1312#endif /* CONFIG_FILS */
Hai Shalom74f70d42019-02-11 14:42:39 -08001313#ifdef TEST_FUZZ
1314 continue_fuzz:
1315#endif /* TEST_FUZZ */
Hai Shalome21d4e82020-04-29 16:34:06 -07001316 sm->MICVerified = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001317 eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm);
1318 sm->pending_1_of_4_timeout = 0;
1319 }
1320
1321 if (key_info & WPA_KEY_INFO_REQUEST) {
1322 if (sm->MICVerified) {
1323 sm->req_replay_counter_used = 1;
1324 os_memcpy(sm->req_replay_counter, key->replay_counter,
1325 WPA_REPLAY_COUNTER_LEN);
1326 } else {
1327 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001328 "received EAPOL-Key request with invalid MIC");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001329 return;
1330 }
1331
1332 /*
1333 * TODO: should decrypt key data field if encryption was used;
1334 * even though MAC address KDE is not normally encrypted,
1335 * supplicant is allowed to encrypt it.
1336 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001337 if (key_info & WPA_KEY_INFO_ERROR) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001338 if (wpa_receive_error_report(
1339 wpa_auth, sm,
1340 !(key_info & WPA_KEY_INFO_KEY_TYPE)) > 0)
1341 return; /* STA entry was removed */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001342 } else if (key_info & WPA_KEY_INFO_KEY_TYPE) {
1343 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001344 "received EAPOL-Key Request for new 4-Way Handshake");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001345 wpa_request_new_ptk(sm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001346 } else if (key_data_length > 0 &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001347 wpa_parse_kde_ies(key_data, key_data_length,
1348 &kde) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001349 kde.mac_addr) {
1350 } else {
1351 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001352 "received EAPOL-Key Request for GTK rekeying");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001353 eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL);
1354 wpa_rekey_gtk(wpa_auth, NULL);
1355 }
1356 } else {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001357 /* Do not allow the same key replay counter to be reused. */
1358 wpa_replay_counter_mark_invalid(sm->key_replay,
1359 key->replay_counter);
1360
1361 if (msg == PAIRWISE_2) {
1362 /*
1363 * Maintain a copy of the pending EAPOL-Key frames in
1364 * case the EAPOL-Key frame was retransmitted. This is
1365 * needed to allow EAPOL-Key msg 2/4 reply to another
1366 * pending msg 1/4 to update the SNonce to work around
1367 * unexpected supplicant behavior.
1368 */
1369 os_memcpy(sm->prev_key_replay, sm->key_replay,
1370 sizeof(sm->key_replay));
1371 } else {
1372 os_memset(sm->prev_key_replay, 0,
1373 sizeof(sm->prev_key_replay));
1374 }
1375
1376 /*
1377 * Make sure old valid counters are not accepted anymore and
1378 * do not get copied again.
1379 */
1380 wpa_replay_counter_mark_invalid(sm->key_replay, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001381 }
1382
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001383 os_free(sm->last_rx_eapol_key);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001384 sm->last_rx_eapol_key = os_memdup(data, data_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07001385 if (!sm->last_rx_eapol_key)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001386 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001387 sm->last_rx_eapol_key_len = data_len;
1388
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001389 sm->rx_eapol_key_secure = !!(key_info & WPA_KEY_INFO_SECURE);
Hai Shalome21d4e82020-04-29 16:34:06 -07001390 sm->EAPOLKeyReceived = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001391 sm->EAPOLKeyPairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE);
1392 sm->EAPOLKeyRequest = !!(key_info & WPA_KEY_INFO_REQUEST);
1393 os_memcpy(sm->SNonce, key->key_nonce, WPA_NONCE_LEN);
1394 wpa_sm_step(sm);
1395}
1396
1397
1398static int wpa_gmk_to_gtk(const u8 *gmk, const char *label, const u8 *addr,
1399 const u8 *gnonce, u8 *gtk, size_t gtk_len)
1400{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001401 u8 data[ETH_ALEN + WPA_NONCE_LEN + 8 + WPA_GTK_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001402 u8 *pos;
1403 int ret = 0;
1404
1405 /* GTK = PRF-X(GMK, "Group key expansion",
1406 * AA || GNonce || Time || random data)
1407 * The example described in the IEEE 802.11 standard uses only AA and
1408 * GNonce as inputs here. Add some more entropy since this derivation
1409 * is done only at the Authenticator and as such, does not need to be
1410 * exactly same.
1411 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001412 os_memset(data, 0, sizeof(data));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001413 os_memcpy(data, addr, ETH_ALEN);
1414 os_memcpy(data + ETH_ALEN, gnonce, WPA_NONCE_LEN);
1415 pos = data + ETH_ALEN + WPA_NONCE_LEN;
1416 wpa_get_ntp_timestamp(pos);
Hai Shalom74f70d42019-02-11 14:42:39 -08001417#ifdef TEST_FUZZ
1418 os_memset(pos, 0xef, 8);
1419#endif /* TEST_FUZZ */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001420 pos += 8;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001421 if (random_get_bytes(pos, gtk_len) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001422 ret = -1;
1423
Roshan Pius3a1667e2018-07-03 15:17:14 -07001424#ifdef CONFIG_SHA384
1425 if (sha384_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data),
1426 gtk, gtk_len) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001427 ret = -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001428#else /* CONFIG_SHA384 */
1429#ifdef CONFIG_SHA256
1430 if (sha256_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data),
1431 gtk, gtk_len) < 0)
1432 ret = -1;
1433#else /* CONFIG_SHA256 */
1434 if (sha1_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data),
1435 gtk, gtk_len) < 0)
1436 ret = -1;
1437#endif /* CONFIG_SHA256 */
1438#endif /* CONFIG_SHA384 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001439
Hai Shalom81f62d82019-07-22 12:10:00 -07001440 forced_memzero(data, sizeof(data));
1441
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001442 return ret;
1443}
1444
1445
1446static void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx)
1447{
1448 struct wpa_authenticator *wpa_auth = eloop_ctx;
1449 struct wpa_state_machine *sm = timeout_ctx;
1450
1451 sm->pending_1_of_4_timeout = 0;
1452 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "EAPOL-Key timeout");
Hai Shalome21d4e82020-04-29 16:34:06 -07001453 sm->TimeoutEvt = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001454 wpa_sm_step(sm);
1455}
1456
1457
1458void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
1459 struct wpa_state_machine *sm, int key_info,
1460 const u8 *key_rsc, const u8 *nonce,
1461 const u8 *kde, size_t kde_len,
1462 int keyidx, int encr, int force_version)
1463{
Hai Shalomfdcde762020-04-02 11:19:20 -07001464 struct wpa_auth_config *conf = &wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001465 struct ieee802_1x_hdr *hdr;
1466 struct wpa_eapol_key *key;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001467 size_t len, mic_len, keyhdrlen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001468 int alg;
1469 int key_data_len, pad_len = 0;
1470 u8 *buf, *pos;
1471 int version, pairwise;
1472 int i;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001473 u8 *key_mic, *key_data;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001474
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001475 mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001476 keyhdrlen = sizeof(*key) + mic_len + 2;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001477
1478 len = sizeof(struct ieee802_1x_hdr) + keyhdrlen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001479
1480 if (force_version)
1481 version = force_version;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001482 else if (wpa_use_akm_defined(sm->wpa_key_mgmt))
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001483 version = WPA_KEY_INFO_TYPE_AKM_DEFINED;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001484 else if (wpa_use_cmac(sm->wpa_key_mgmt))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001485 version = WPA_KEY_INFO_TYPE_AES_128_CMAC;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001486 else if (sm->pairwise != WPA_CIPHER_TKIP)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001487 version = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;
1488 else
1489 version = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
1490
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001491 pairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001492
Hai Shalomfdcde762020-04-02 11:19:20 -07001493 wpa_printf(MSG_DEBUG,
1494 "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 -07001495 version,
1496 (key_info & WPA_KEY_INFO_SECURE) ? 1 : 0,
1497 (key_info & WPA_KEY_INFO_MIC) ? 1 : 0,
1498 (key_info & WPA_KEY_INFO_ACK) ? 1 : 0,
1499 (key_info & WPA_KEY_INFO_INSTALL) ? 1 : 0,
Hai Shalomfdcde762020-04-02 11:19:20 -07001500 pairwise, kde_len, keyidx, encr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001501
1502 key_data_len = kde_len;
1503
1504 if ((version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
Roshan Pius3a1667e2018-07-03 15:17:14 -07001505 wpa_use_aes_key_wrap(sm->wpa_key_mgmt) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001506 version == WPA_KEY_INFO_TYPE_AES_128_CMAC) && encr) {
1507 pad_len = key_data_len % 8;
1508 if (pad_len)
1509 pad_len = 8 - pad_len;
1510 key_data_len += pad_len + 8;
1511 }
1512
1513 len += key_data_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001514 if (!mic_len && encr)
1515 len += AES_BLOCK_SIZE;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001516
1517 hdr = os_zalloc(len);
Hai Shalomfdcde762020-04-02 11:19:20 -07001518 if (!hdr)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001519 return;
Hai Shalomfdcde762020-04-02 11:19:20 -07001520 hdr->version = conf->eapol_version;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001521 hdr->type = IEEE802_1X_TYPE_EAPOL_KEY;
1522 hdr->length = host_to_be16(len - sizeof(*hdr));
1523 key = (struct wpa_eapol_key *) (hdr + 1);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001524 key_mic = (u8 *) (key + 1);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001525 key_data = ((u8 *) (hdr + 1)) + keyhdrlen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001526
1527 key->type = sm->wpa == WPA_VERSION_WPA2 ?
1528 EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
1529 key_info |= version;
1530 if (encr && sm->wpa == WPA_VERSION_WPA2)
1531 key_info |= WPA_KEY_INFO_ENCR_KEY_DATA;
1532 if (sm->wpa != WPA_VERSION_WPA2)
1533 key_info |= keyidx << WPA_KEY_INFO_KEY_INDEX_SHIFT;
1534 WPA_PUT_BE16(key->key_info, key_info);
1535
Hai Shalomfdcde762020-04-02 11:19:20 -07001536 alg = pairwise ? sm->pairwise : conf->wpa_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001537 if (sm->wpa == WPA_VERSION_WPA2 && !pairwise)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001538 WPA_PUT_BE16(key->key_length, 0);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001539 else
1540 WPA_PUT_BE16(key->key_length, wpa_cipher_key_len(alg));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001541
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001542 for (i = RSNA_MAX_EAPOL_RETRIES - 1; i > 0; i--) {
1543 sm->key_replay[i].valid = sm->key_replay[i - 1].valid;
1544 os_memcpy(sm->key_replay[i].counter,
1545 sm->key_replay[i - 1].counter,
1546 WPA_REPLAY_COUNTER_LEN);
1547 }
1548 inc_byte_array(sm->key_replay[0].counter, WPA_REPLAY_COUNTER_LEN);
1549 os_memcpy(key->replay_counter, sm->key_replay[0].counter,
1550 WPA_REPLAY_COUNTER_LEN);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001551 wpa_hexdump(MSG_DEBUG, "WPA: Replay Counter",
1552 key->replay_counter, WPA_REPLAY_COUNTER_LEN);
Hai Shalome21d4e82020-04-29 16:34:06 -07001553 sm->key_replay[0].valid = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001554
1555 if (nonce)
1556 os_memcpy(key->key_nonce, nonce, WPA_NONCE_LEN);
1557
1558 if (key_rsc)
1559 os_memcpy(key->key_rsc, key_rsc, WPA_KEY_RSC_LEN);
1560
1561 if (kde && !encr) {
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001562 os_memcpy(key_data, kde, kde_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001563 WPA_PUT_BE16(key_mic + mic_len, kde_len);
1564#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07001565 } else if (!mic_len && kde) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001566 const u8 *aad[1];
1567 size_t aad_len[1];
1568
1569 WPA_PUT_BE16(key_mic, AES_BLOCK_SIZE + kde_len);
1570 wpa_hexdump_key(MSG_DEBUG, "Plaintext EAPOL-Key Key Data",
1571 kde, kde_len);
1572
1573 wpa_hexdump_key(MSG_DEBUG, "WPA: KEK",
1574 sm->PTK.kek, sm->PTK.kek_len);
1575 /* AES-SIV AAD from EAPOL protocol version field (inclusive) to
1576 * to Key Data (exclusive). */
1577 aad[0] = (u8 *) hdr;
1578 aad_len[0] = key_mic + 2 - (u8 *) hdr;
1579 if (aes_siv_encrypt(sm->PTK.kek, sm->PTK.kek_len, kde, kde_len,
1580 1, aad, aad_len, key_mic + 2) < 0) {
1581 wpa_printf(MSG_DEBUG, "WPA: AES-SIV encryption failed");
1582 return;
1583 }
1584
1585 wpa_hexdump(MSG_DEBUG, "WPA: Encrypted Key Data from SIV",
1586 key_mic + 2, AES_BLOCK_SIZE + kde_len);
1587#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001588 } else if (encr && kde) {
1589 buf = os_zalloc(key_data_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07001590 if (!buf) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001591 os_free(hdr);
1592 return;
1593 }
1594 pos = buf;
1595 os_memcpy(pos, kde, kde_len);
1596 pos += kde_len;
1597
1598 if (pad_len)
1599 *pos++ = 0xdd;
1600
1601 wpa_hexdump_key(MSG_DEBUG, "Plaintext EAPOL-Key Key Data",
1602 buf, key_data_len);
1603 if (version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
Roshan Pius3a1667e2018-07-03 15:17:14 -07001604 wpa_use_aes_key_wrap(sm->wpa_key_mgmt) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001605 version == WPA_KEY_INFO_TYPE_AES_128_CMAC) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001606 wpa_printf(MSG_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07001607 "WPA: Encrypt Key Data using AES-WRAP (KEK length %zu)",
1608 sm->PTK.kek_len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001609 if (aes_wrap(sm->PTK.kek, sm->PTK.kek_len,
1610 (key_data_len - 8) / 8, buf, key_data)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001611 os_free(hdr);
1612 os_free(buf);
1613 return;
1614 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001615 WPA_PUT_BE16(key_mic + mic_len, key_data_len);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001616#ifndef CONFIG_NO_RC4
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001617 } else if (sm->PTK.kek_len == 16) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001618 u8 ek[32];
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001619
1620 wpa_printf(MSG_DEBUG,
1621 "WPA: Encrypt Key Data using RC4");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001622 os_memcpy(key->key_iv,
1623 sm->group->Counter + WPA_NONCE_LEN - 16, 16);
1624 inc_byte_array(sm->group->Counter, WPA_NONCE_LEN);
1625 os_memcpy(ek, key->key_iv, 16);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001626 os_memcpy(ek + 16, sm->PTK.kek, sm->PTK.kek_len);
1627 os_memcpy(key_data, buf, key_data_len);
1628 rc4_skip(ek, 32, 256, key_data, key_data_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001629 WPA_PUT_BE16(key_mic + mic_len, key_data_len);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001630#endif /* CONFIG_NO_RC4 */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001631 } else {
1632 os_free(hdr);
1633 os_free(buf);
1634 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001635 }
1636 os_free(buf);
1637 }
1638
1639 if (key_info & WPA_KEY_INFO_MIC) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001640 if (!sm->PTK_valid || !mic_len) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001641 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07001642 "PTK not valid when sending EAPOL-Key frame");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001643 os_free(hdr);
1644 return;
1645 }
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001646
Roshan Pius3a1667e2018-07-03 15:17:14 -07001647 if (wpa_eapol_key_mic(sm->PTK.kck, sm->PTK.kck_len,
1648 sm->wpa_key_mgmt, version,
1649 (u8 *) hdr, len, key_mic) < 0) {
1650 os_free(hdr);
1651 return;
1652 }
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001653#ifdef CONFIG_TESTING_OPTIONS
1654 if (!pairwise &&
Hai Shalomfdcde762020-04-02 11:19:20 -07001655 conf->corrupt_gtk_rekey_mic_probability > 0.0 &&
1656 drand48() < conf->corrupt_gtk_rekey_mic_probability) {
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001657 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
1658 "Corrupting group EAPOL-Key Key MIC");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001659 key_mic[0]++;
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001660 }
1661#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001662 }
1663
Hai Shalomfdcde762020-04-02 11:19:20 -07001664 wpa_auth_set_eapol(wpa_auth, sm->addr, WPA_EAPOL_inc_EapolFramesTx, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001665 wpa_auth_send_eapol(wpa_auth, sm->addr, (u8 *) hdr, len,
1666 sm->pairwise_set);
1667 os_free(hdr);
1668}
1669
1670
1671static void wpa_send_eapol(struct wpa_authenticator *wpa_auth,
1672 struct wpa_state_machine *sm, int key_info,
1673 const u8 *key_rsc, const u8 *nonce,
1674 const u8 *kde, size_t kde_len,
1675 int keyidx, int encr)
1676{
1677 int timeout_ms;
1678 int pairwise = key_info & WPA_KEY_INFO_KEY_TYPE;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001679 u32 ctr;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001680
Hai Shalomfdcde762020-04-02 11:19:20 -07001681 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001682 return;
1683
1684 __wpa_send_eapol(wpa_auth, sm, key_info, key_rsc, nonce, kde, kde_len,
1685 keyidx, encr, 0);
1686
1687 ctr = pairwise ? sm->TimeoutCtr : sm->GTimeoutCtr;
1688 if (ctr == 1 && wpa_auth->conf.tx_status)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001689 timeout_ms = pairwise ? eapol_key_timeout_first :
1690 eapol_key_timeout_first_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001691 else
1692 timeout_ms = eapol_key_timeout_subseq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001693 if (wpa_auth->conf.wpa_disable_eapol_key_retries &&
1694 (!pairwise || (key_info & WPA_KEY_INFO_MIC)))
1695 timeout_ms = eapol_key_timeout_no_retrans;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001696 if (pairwise && ctr == 1 && !(key_info & WPA_KEY_INFO_MIC))
1697 sm->pending_1_of_4_timeout = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08001698#ifdef TEST_FUZZ
1699 timeout_ms = 1;
1700#endif /* TEST_FUZZ */
Hai Shalomfdcde762020-04-02 11:19:20 -07001701 wpa_printf(MSG_DEBUG,
1702 "WPA: Use EAPOL-Key timeout of %u ms (retry counter %u)",
1703 timeout_ms, ctr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001704 eloop_register_timeout(timeout_ms / 1000, (timeout_ms % 1000) * 1000,
1705 wpa_send_eapol_timeout, wpa_auth, sm);
1706}
1707
1708
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001709static int wpa_verify_key_mic(int akmp, size_t pmk_len, struct wpa_ptk *PTK,
1710 u8 *data, size_t data_len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001711{
1712 struct ieee802_1x_hdr *hdr;
1713 struct wpa_eapol_key *key;
1714 u16 key_info;
1715 int ret = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001716 u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN], *mic_pos;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001717 size_t mic_len = wpa_mic_len(akmp, pmk_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001718
1719 if (data_len < sizeof(*hdr) + sizeof(*key))
1720 return -1;
1721
1722 hdr = (struct ieee802_1x_hdr *) data;
1723 key = (struct wpa_eapol_key *) (hdr + 1);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001724 mic_pos = (u8 *) (key + 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001725 key_info = WPA_GET_BE16(key->key_info);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001726 os_memcpy(mic, mic_pos, mic_len);
1727 os_memset(mic_pos, 0, mic_len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001728 if (wpa_eapol_key_mic(PTK->kck, PTK->kck_len, akmp,
1729 key_info & WPA_KEY_INFO_TYPE_MASK,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001730 data, data_len, mic_pos) ||
1731 os_memcmp_const(mic, mic_pos, mic_len) != 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001732 ret = -1;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001733 os_memcpy(mic_pos, mic, mic_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001734 return ret;
1735}
1736
1737
1738void wpa_remove_ptk(struct wpa_state_machine *sm)
1739{
Hai Shalome21d4e82020-04-29 16:34:06 -07001740 sm->PTK_valid = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001741 os_memset(&sm->PTK, 0, sizeof(sm->PTK));
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001742 if (wpa_auth_set_key(sm->wpa_auth, 0, WPA_ALG_NONE, sm->addr, 0, NULL,
Hai Shalomfdcde762020-04-02 11:19:20 -07001743 0, KEY_FLAG_PAIRWISE))
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001744 wpa_printf(MSG_DEBUG,
1745 "RSN: PTK removal from the driver failed");
Hai Shalomfdcde762020-04-02 11:19:20 -07001746 if (sm->use_ext_key_id &&
1747 wpa_auth_set_key(sm->wpa_auth, 0, WPA_ALG_NONE, sm->addr, 1, NULL,
1748 0, KEY_FLAG_PAIRWISE))
1749 wpa_printf(MSG_DEBUG,
1750 "RSN: PTK Key ID 1 removal from the driver failed");
Hai Shalome21d4e82020-04-29 16:34:06 -07001751 sm->pairwise_set = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001752 eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm);
1753}
1754
1755
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001756int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001757{
1758 int remove_ptk = 1;
1759
Hai Shalomfdcde762020-04-02 11:19:20 -07001760 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001761 return -1;
1762
1763 wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
1764 "event %d notification", event);
1765
1766 switch (event) {
1767 case WPA_AUTH:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001768#ifdef CONFIG_MESH
1769 /* PTKs are derived through AMPE */
1770 if (wpa_auth_start_ampe(sm->wpa_auth, sm->addr)) {
1771 /* not mesh */
1772 break;
1773 }
1774 return 0;
1775#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001776 case WPA_ASSOC:
1777 break;
1778 case WPA_DEAUTH:
1779 case WPA_DISASSOC:
Hai Shalome21d4e82020-04-29 16:34:06 -07001780 sm->DeauthenticationRequest = true;
Hai Shalom1dc4d202019-04-29 16:22:27 -07001781#ifdef CONFIG_IEEE80211R_AP
1782 os_memset(sm->PMK, 0, sizeof(sm->PMK));
1783 sm->pmk_len = 0;
1784 os_memset(sm->xxkey, 0, sizeof(sm->xxkey));
1785 sm->xxkey_len = 0;
Hai Shalom81f62d82019-07-22 12:10:00 -07001786 os_memset(sm->pmk_r1, 0, sizeof(sm->pmk_r1));
1787 sm->pmk_r1_len = 0;
Hai Shalom1dc4d202019-04-29 16:22:27 -07001788#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001789 break;
1790 case WPA_REAUTH:
1791 case WPA_REAUTH_EAPOL:
1792 if (!sm->started) {
1793 /*
1794 * When using WPS, we may end up here if the STA
1795 * manages to re-associate without the previous STA
1796 * entry getting removed. Consequently, we need to make
1797 * sure that the WPA state machines gets initialized
1798 * properly at this point.
1799 */
Hai Shalomfdcde762020-04-02 11:19:20 -07001800 wpa_printf(MSG_DEBUG,
1801 "WPA state machine had not been started - initialize now");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001802 sm->started = 1;
Hai Shalome21d4e82020-04-29 16:34:06 -07001803 sm->Init = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001804 if (wpa_sm_step(sm) == 1)
1805 return 1; /* should not really happen */
Hai Shalome21d4e82020-04-29 16:34:06 -07001806 sm->Init = false;
1807 sm->AuthenticationRequest = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001808 break;
1809 }
Hai Shalomfdcde762020-04-02 11:19:20 -07001810
1811 if (!sm->use_ext_key_id &&
1812 sm->wpa_auth->conf.wpa_deny_ptk0_rekey) {
1813 wpa_printf(MSG_INFO,
1814 "WPA: PTK0 rekey not allowed, disconnect "
1815 MACSTR, MAC2STR(sm->addr));
Hai Shalome21d4e82020-04-29 16:34:06 -07001816 sm->Disconnect = true;
Hai Shalomfdcde762020-04-02 11:19:20 -07001817 /* Try to encourage the STA to reconnect */
1818 sm->disconnect_reason =
1819 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA;
1820 break;
1821 }
1822
1823 if (sm->use_ext_key_id)
1824 sm->keyidx_active ^= 1; /* flip Key ID */
1825
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001826 if (sm->GUpdateStationKeys) {
1827 /*
1828 * Reauthentication cancels the pending group key
1829 * update for this STA.
1830 */
1831 sm->group->GKeyDoneStations--;
Hai Shalome21d4e82020-04-29 16:34:06 -07001832 sm->GUpdateStationKeys = false;
1833 sm->PtkGroupInit = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001834 }
Hai Shalome21d4e82020-04-29 16:34:06 -07001835 sm->ReAuthenticationRequest = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001836 break;
1837 case WPA_ASSOC_FT:
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001838#ifdef CONFIG_IEEE80211R_AP
Hai Shalomfdcde762020-04-02 11:19:20 -07001839 wpa_printf(MSG_DEBUG,
1840 "FT: Retry PTK configuration after association");
Hai Shalomb755a2a2020-04-23 21:49:02 -07001841 wpa_ft_install_ptk(sm, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001842
1843 /* Using FT protocol, not WPA auth state machine */
1844 sm->ft_completed = 1;
Hai Shalom81f62d82019-07-22 12:10:00 -07001845 wpa_auth_set_ptk_rekey_timer(sm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001846 return 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001847#else /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001848 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001849#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001850 case WPA_ASSOC_FILS:
1851#ifdef CONFIG_FILS
1852 wpa_printf(MSG_DEBUG,
1853 "FILS: TK configuration after association");
1854 fils_set_tk(sm);
1855 sm->fils_completed = 1;
1856 return 0;
1857#else /* CONFIG_FILS */
1858 break;
1859#endif /* CONFIG_FILS */
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02001860 case WPA_DRV_STA_REMOVED:
Hai Shalome21d4e82020-04-29 16:34:06 -07001861 sm->tk_already_set = false;
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02001862 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001863 }
1864
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001865#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001866 sm->ft_completed = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001867#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001868
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001869 if (sm->mgmt_frame_prot && event == WPA_AUTH)
1870 remove_ptk = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001871#ifdef CONFIG_FILS
1872 if (wpa_key_mgmt_fils(sm->wpa_key_mgmt) &&
1873 (event == WPA_AUTH || event == WPA_ASSOC))
1874 remove_ptk = 0;
1875#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001876
1877 if (remove_ptk) {
Hai Shalome21d4e82020-04-29 16:34:06 -07001878 sm->PTK_valid = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001879 os_memset(&sm->PTK, 0, sizeof(sm->PTK));
1880
1881 if (event != WPA_REAUTH_EAPOL)
1882 wpa_remove_ptk(sm);
1883 }
1884
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001885 if (sm->in_step_loop) {
1886 /*
1887 * wpa_sm_step() is already running - avoid recursive call to
1888 * it by making the existing loop process the new update.
1889 */
Hai Shalome21d4e82020-04-29 16:34:06 -07001890 sm->changed = true;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001891 return 0;
1892 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001893 return wpa_sm_step(sm);
1894}
1895
1896
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001897SM_STATE(WPA_PTK, INITIALIZE)
1898{
1899 SM_ENTRY_MA(WPA_PTK, INITIALIZE, wpa_ptk);
1900 if (sm->Init) {
1901 /* Init flag is not cleared here, so avoid busy
1902 * loop by claiming nothing changed. */
Hai Shalome21d4e82020-04-29 16:34:06 -07001903 sm->changed = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001904 }
1905
1906 sm->keycount = 0;
1907 if (sm->GUpdateStationKeys)
1908 sm->group->GKeyDoneStations--;
Hai Shalome21d4e82020-04-29 16:34:06 -07001909 sm->GUpdateStationKeys = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001910 if (sm->wpa == WPA_VERSION_WPA)
Hai Shalome21d4e82020-04-29 16:34:06 -07001911 sm->PInitAKeys = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001912 if (1 /* Unicast cipher supported AND (ESS OR ((IBSS or WDS) and
1913 * Local AA > Remote AA)) */) {
Hai Shalome21d4e82020-04-29 16:34:06 -07001914 sm->Pair = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001915 }
1916 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 0);
1917 wpa_remove_ptk(sm);
1918 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid, 0);
1919 sm->TimeoutCtr = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001920 if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
1921 sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP ||
1922 sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001923 wpa_auth_set_eapol(sm->wpa_auth, sm->addr,
1924 WPA_EAPOL_authorized, 0);
1925 }
1926}
1927
1928
1929SM_STATE(WPA_PTK, DISCONNECT)
1930{
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001931 u16 reason = sm->disconnect_reason;
1932
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001933 SM_ENTRY_MA(WPA_PTK, DISCONNECT, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07001934 sm->Disconnect = false;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001935 sm->disconnect_reason = 0;
1936 if (!reason)
1937 reason = WLAN_REASON_PREV_AUTH_NOT_VALID;
1938 wpa_sta_disconnect(sm->wpa_auth, sm->addr, reason);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001939}
1940
1941
1942SM_STATE(WPA_PTK, DISCONNECTED)
1943{
1944 SM_ENTRY_MA(WPA_PTK, DISCONNECTED, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07001945 sm->DeauthenticationRequest = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001946}
1947
1948
1949SM_STATE(WPA_PTK, AUTHENTICATION)
1950{
1951 SM_ENTRY_MA(WPA_PTK, AUTHENTICATION, wpa_ptk);
1952 os_memset(&sm->PTK, 0, sizeof(sm->PTK));
Hai Shalome21d4e82020-04-29 16:34:06 -07001953 sm->PTK_valid = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001954 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portControl_Auto,
1955 1);
1956 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 1);
Hai Shalome21d4e82020-04-29 16:34:06 -07001957 sm->AuthenticationRequest = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001958}
1959
1960
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001961static void wpa_group_ensure_init(struct wpa_authenticator *wpa_auth,
1962 struct wpa_group *group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001963{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001964 if (group->first_sta_seen)
1965 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001966 /*
1967 * System has run bit further than at the time hostapd was started
1968 * potentially very early during boot up. This provides better chances
1969 * of collecting more randomness on embedded systems. Re-initialize the
1970 * GMK and Counter here to improve their strength if there was not
1971 * enough entropy available immediately after system startup.
1972 */
Hai Shalomfdcde762020-04-02 11:19:20 -07001973 wpa_printf(MSG_DEBUG,
1974 "WPA: Re-initialize GMK/Counter on first station");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001975 if (random_pool_ready() != 1) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001976 wpa_printf(MSG_INFO,
1977 "WPA: Not enough entropy in random pool to proceed - reject first 4-way handshake");
Hai Shalome21d4e82020-04-29 16:34:06 -07001978 group->reject_4way_hs_for_entropy = true;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001979 } else {
Hai Shalome21d4e82020-04-29 16:34:06 -07001980 group->first_sta_seen = true;
1981 group->reject_4way_hs_for_entropy = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001982 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001983
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001984 if (wpa_group_init_gmk_and_counter(wpa_auth, group) < 0 ||
1985 wpa_gtk_update(wpa_auth, group) < 0 ||
1986 wpa_group_config_group_keys(wpa_auth, group) < 0) {
1987 wpa_printf(MSG_INFO, "WPA: GMK/GTK setup failed");
Hai Shalome21d4e82020-04-29 16:34:06 -07001988 group->first_sta_seen = false;
1989 group->reject_4way_hs_for_entropy = true;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001990 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001991}
1992
1993
1994SM_STATE(WPA_PTK, AUTHENTICATION2)
1995{
1996 SM_ENTRY_MA(WPA_PTK, AUTHENTICATION2, wpa_ptk);
1997
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001998 wpa_group_ensure_init(sm->wpa_auth, sm->group);
Hai Shalome21d4e82020-04-29 16:34:06 -07001999 sm->ReAuthenticationRequest = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002000
Dmitry Shmidt04949592012-07-19 12:16:46 -07002001 /*
2002 * Definition of ANonce selection in IEEE Std 802.11i-2004 is somewhat
2003 * ambiguous. The Authenticator state machine uses a counter that is
2004 * incremented by one for each 4-way handshake. However, the security
2005 * analysis of 4-way handshake points out that unpredictable nonces
2006 * help in preventing precomputation attacks. Instead of the state
2007 * machine definition, use an unpredictable nonce value here to provide
2008 * stronger protection against potential precomputation attacks.
2009 */
2010 if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) {
Hai Shalomfdcde762020-04-02 11:19:20 -07002011 wpa_printf(MSG_ERROR,
2012 "WPA: Failed to get random data for ANonce.");
Hai Shalome21d4e82020-04-29 16:34:06 -07002013 sm->Disconnect = true;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002014 return;
2015 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002016 wpa_hexdump(MSG_DEBUG, "WPA: Assign ANonce", sm->ANonce,
2017 WPA_NONCE_LEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002018 /* IEEE 802.11i does not clear TimeoutCtr here, but this is more
2019 * logical place than INITIALIZE since AUTHENTICATION2 can be
2020 * re-entered on ReAuthenticationRequest without going through
2021 * INITIALIZE. */
2022 sm->TimeoutCtr = 0;
2023}
2024
2025
Jouni Malinen1420a892017-10-01 12:32:57 +03002026static int wpa_auth_sm_ptk_update(struct wpa_state_machine *sm)
2027{
2028 if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) {
2029 wpa_printf(MSG_ERROR,
2030 "WPA: Failed to get random data for ANonce");
Hai Shalome21d4e82020-04-29 16:34:06 -07002031 sm->Disconnect = true;
Jouni Malinen1420a892017-10-01 12:32:57 +03002032 return -1;
2033 }
2034 wpa_hexdump(MSG_DEBUG, "WPA: Assign new ANonce", sm->ANonce,
2035 WPA_NONCE_LEN);
2036 sm->TimeoutCtr = 0;
2037 return 0;
2038}
2039
2040
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002041SM_STATE(WPA_PTK, INITPMK)
2042{
2043 u8 msk[2 * PMK_LEN];
2044 size_t len = 2 * PMK_LEN;
2045
2046 SM_ENTRY_MA(WPA_PTK, INITPMK, wpa_ptk);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002047#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002048 sm->xxkey_len = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002049#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002050 if (sm->pmksa) {
2051 wpa_printf(MSG_DEBUG, "WPA: PMK from PMKSA cache");
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002052 os_memcpy(sm->PMK, sm->pmksa->pmk, sm->pmksa->pmk_len);
2053 sm->pmk_len = sm->pmksa->pmk_len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002054#ifdef CONFIG_DPP
2055 } else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP) {
2056 wpa_printf(MSG_DEBUG,
2057 "DPP: No PMKSA cache entry for STA - reject connection");
Hai Shalome21d4e82020-04-29 16:34:06 -07002058 sm->Disconnect = true;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002059 sm->disconnect_reason = WLAN_REASON_INVALID_PMKID;
2060 return;
2061#endif /* CONFIG_DPP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002062 } else if (wpa_auth_get_msk(sm->wpa_auth, sm->addr, msk, &len) == 0) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002063 unsigned int pmk_len;
2064
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002065 if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002066 pmk_len = PMK_LEN_SUITE_B_192;
2067 else
2068 pmk_len = PMK_LEN;
Hai Shalomfdcde762020-04-02 11:19:20 -07002069 wpa_printf(MSG_DEBUG,
2070 "WPA: PMK from EAPOL state machine (MSK len=%zu PMK len=%u)",
2071 len, pmk_len);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002072 if (len < pmk_len) {
2073 wpa_printf(MSG_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07002074 "WPA: MSK not long enough (%zu) to create PMK (%u)",
2075 len, pmk_len);
Hai Shalome21d4e82020-04-29 16:34:06 -07002076 sm->Disconnect = true;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002077 return;
2078 }
2079 os_memcpy(sm->PMK, msk, pmk_len);
2080 sm->pmk_len = pmk_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002081#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002082 if (len >= 2 * PMK_LEN) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002083 if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) {
2084 os_memcpy(sm->xxkey, msk, SHA384_MAC_LEN);
2085 sm->xxkey_len = SHA384_MAC_LEN;
2086 } else {
2087 os_memcpy(sm->xxkey, msk + PMK_LEN, PMK_LEN);
2088 sm->xxkey_len = PMK_LEN;
2089 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002090 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002091#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002092 } else {
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002093 wpa_printf(MSG_DEBUG, "WPA: Could not get PMK, get_msk: %p",
Paul Stewart092955c2017-02-06 09:13:09 -08002094 sm->wpa_auth->cb->get_msk);
Hai Shalome21d4e82020-04-29 16:34:06 -07002095 sm->Disconnect = true;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002096 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002097 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002098 forced_memzero(msk, sizeof(msk));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002099
2100 sm->req_replay_counter_used = 0;
Hai Shalome21d4e82020-04-29 16:34:06 -07002101 /* IEEE 802.11i does not set keyRun to false, but not doing this
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002102 * will break reauthentication since EAPOL state machines may not be
2103 * get into AUTHENTICATING state that clears keyRun before WPA state
2104 * machine enters AUTHENTICATION2 state and goes immediately to INITPMK
2105 * state and takes PMK from the previously used AAA Key. This will
2106 * eventually fail in 4-Way Handshake because Supplicant uses PMK
Hai Shalome21d4e82020-04-29 16:34:06 -07002107 * derived from the new AAA Key. Setting keyRun = false here seems to
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002108 * be good workaround for this issue. */
Hai Shalome21d4e82020-04-29 16:34:06 -07002109 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyRun, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002110}
2111
2112
2113SM_STATE(WPA_PTK, INITPSK)
2114{
2115 const u8 *psk;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002116 size_t psk_len;
2117
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002118 SM_ENTRY_MA(WPA_PTK, INITPSK, wpa_ptk);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002119 psk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr, NULL,
Hai Shalom021b0b52019-04-10 11:17:58 -07002120 &psk_len, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002121 if (psk) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002122 os_memcpy(sm->PMK, psk, psk_len);
2123 sm->pmk_len = psk_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002124#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002125 os_memcpy(sm->xxkey, psk, PMK_LEN);
2126 sm->xxkey_len = PMK_LEN;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002127#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002128 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002129#ifdef CONFIG_SAE
2130 if (wpa_auth_uses_sae(sm) && sm->pmksa) {
2131 wpa_printf(MSG_DEBUG, "SAE: PMK from PMKSA cache");
2132 os_memcpy(sm->PMK, sm->pmksa->pmk, sm->pmksa->pmk_len);
2133 sm->pmk_len = sm->pmksa->pmk_len;
Hai Shalom021b0b52019-04-10 11:17:58 -07002134#ifdef CONFIG_IEEE80211R_AP
2135 os_memcpy(sm->xxkey, sm->pmksa->pmk, sm->pmksa->pmk_len);
2136 sm->xxkey_len = sm->pmksa->pmk_len;
2137#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002138 }
2139#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002140 sm->req_replay_counter_used = 0;
2141}
2142
2143
2144SM_STATE(WPA_PTK, PTKSTART)
2145{
2146 u8 buf[2 + RSN_SELECTOR_LEN + PMKID_LEN], *pmkid = NULL;
2147 size_t pmkid_len = 0;
2148
2149 SM_ENTRY_MA(WPA_PTK, PTKSTART, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07002150 sm->PTKRequest = false;
2151 sm->TimeoutEvt = false;
2152 sm->alt_snonce_valid = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002153
2154 sm->TimeoutCtr++;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002155 if (sm->TimeoutCtr > sm->wpa_auth->conf.wpa_pairwise_update_count) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002156 /* No point in sending the EAPOL-Key - we will disconnect
2157 * immediately following this. */
2158 return;
2159 }
2160
2161 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
2162 "sending 1/4 msg of 4-Way Handshake");
2163 /*
Hai Shalomce48b4a2018-09-05 11:41:35 -07002164 * For infrastructure BSS cases, it is better for the AP not to include
2165 * the PMKID KDE in EAPOL-Key msg 1/4 since it could be used to initiate
2166 * offline search for the passphrase/PSK without having to be able to
2167 * capture a 4-way handshake from a STA that has access to the network.
2168 *
2169 * For IBSS cases, addition of PMKID KDE could be considered even with
2170 * WPA2-PSK cases that use multiple PSKs, but only if there is a single
2171 * possible PSK for this STA. However, this should not be done unless
2172 * there is support for using that information on the supplicant side.
2173 * The concern about exposing PMKID unnecessarily in infrastructure BSS
2174 * cases would also apply here, but at least in the IBSS case, this
2175 * would cover a potential real use case.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002176 */
2177 if (sm->wpa == WPA_VERSION_WPA2 &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002178 (wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) ||
2179 (sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE && sm->pmksa) ||
2180 wpa_key_mgmt_sae(sm->wpa_key_mgmt)) &&
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002181 sm->wpa_key_mgmt != WPA_KEY_MGMT_OSEN) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002182 pmkid = buf;
2183 pmkid_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN;
2184 pmkid[0] = WLAN_EID_VENDOR_SPECIFIC;
2185 pmkid[1] = RSN_SELECTOR_LEN + PMKID_LEN;
2186 RSN_SELECTOR_PUT(&pmkid[2], RSN_KEY_DATA_PMKID);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002187 if (sm->pmksa) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002188 wpa_hexdump(MSG_DEBUG,
2189 "RSN: Message 1/4 PMKID from PMKSA entry",
2190 sm->pmksa->pmkid, PMKID_LEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002191 os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN],
2192 sm->pmksa->pmkid, PMKID_LEN);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002193 } else if (wpa_key_mgmt_suite_b(sm->wpa_key_mgmt)) {
2194 /* No KCK available to derive PMKID */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002195 wpa_printf(MSG_DEBUG,
2196 "RSN: No KCK available to derive PMKID for message 1/4");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002197 pmkid = NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -07002198#ifdef CONFIG_FILS
2199 } else if (wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
2200 if (sm->pmkid_set) {
2201 wpa_hexdump(MSG_DEBUG,
2202 "RSN: Message 1/4 PMKID from FILS/ERP",
2203 sm->pmkid, PMKID_LEN);
2204 os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN],
2205 sm->pmkid, PMKID_LEN);
2206 } else {
2207 /* No PMKID available */
2208 wpa_printf(MSG_DEBUG,
2209 "RSN: No FILS/ERP PMKID available for message 1/4");
2210 pmkid = NULL;
2211 }
2212#endif /* CONFIG_FILS */
2213#ifdef CONFIG_IEEE80211R_AP
2214 } else if (wpa_key_mgmt_ft(sm->wpa_key_mgmt) &&
2215 sm->ft_completed) {
2216 wpa_printf(MSG_DEBUG,
2217 "FT: No PMKID in message 1/4 when using FT protocol");
2218 pmkid = NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -07002219#endif /* CONFIG_IEEE80211R_AP */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002220#ifdef CONFIG_SAE
2221 } else if (wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
2222 if (sm->pmkid_set) {
2223 wpa_hexdump(MSG_DEBUG,
2224 "RSN: Message 1/4 PMKID from SAE",
2225 sm->pmkid, PMKID_LEN);
2226 os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN],
2227 sm->pmkid, PMKID_LEN);
2228 } else {
2229 /* No PMKID available */
2230 wpa_printf(MSG_DEBUG,
2231 "RSN: No SAE PMKID available for message 1/4");
2232 pmkid = NULL;
2233 }
2234#endif /* CONFIG_SAE */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002235 } else {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002236 /*
2237 * Calculate PMKID since no PMKSA cache entry was
2238 * available with pre-calculated PMKID.
2239 */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002240 rsn_pmkid(sm->PMK, sm->pmk_len, sm->wpa_auth->addr,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002241 sm->addr, &pmkid[2 + RSN_SELECTOR_LEN],
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002242 sm->wpa_key_mgmt);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002243 wpa_hexdump(MSG_DEBUG,
2244 "RSN: Message 1/4 PMKID derived from PMK",
2245 &pmkid[2 + RSN_SELECTOR_LEN], PMKID_LEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002246 }
2247 }
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002248 if (!pmkid)
2249 pmkid_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002250 wpa_send_eapol(sm->wpa_auth, sm,
2251 WPA_KEY_INFO_ACK | WPA_KEY_INFO_KEY_TYPE, NULL,
2252 sm->ANonce, pmkid, pmkid_len, 0, 0);
2253}
2254
2255
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002256static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002257 const u8 *pmk, unsigned int pmk_len,
Hai Shalomfdcde762020-04-02 11:19:20 -07002258 struct wpa_ptk *ptk, int force_sha256)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002259{
Hai Shalom021b0b52019-04-10 11:17:58 -07002260 const u8 *z = NULL;
2261 size_t z_len = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002262 int akmp;
Hai Shalom021b0b52019-04-10 11:17:58 -07002263
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002264#ifdef CONFIG_IEEE80211R_AP
Hai Shalom81f62d82019-07-22 12:10:00 -07002265 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
2266 if (sm->ft_completed) {
2267 u8 ptk_name[WPA_PMK_NAME_LEN];
2268
2269 return wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->pmk_r1_len,
2270 sm->SNonce, sm->ANonce,
2271 sm->addr, sm->wpa_auth->addr,
2272 sm->pmk_r1_name,
2273 ptk, ptk_name,
2274 sm->wpa_key_mgmt,
2275 sm->pairwise);
2276 }
2277 return wpa_auth_derive_ptk_ft(sm, ptk);
2278 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002279#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002280
Hai Shalom021b0b52019-04-10 11:17:58 -07002281#ifdef CONFIG_DPP2
2282 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP && sm->dpp_z) {
2283 z = wpabuf_head(sm->dpp_z);
2284 z_len = wpabuf_len(sm->dpp_z);
2285 }
2286#endif /* CONFIG_DPP2 */
2287
Hai Shalomfdcde762020-04-02 11:19:20 -07002288 akmp = sm->wpa_key_mgmt;
2289 if (force_sha256)
2290 akmp |= WPA_KEY_MGMT_PSK_SHA256;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002291 return wpa_pmk_to_ptk(pmk, pmk_len, "Pairwise key expansion",
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002292 sm->wpa_auth->addr, sm->addr, sm->ANonce, snonce,
Hai Shalomfdcde762020-04-02 11:19:20 -07002293 ptk, akmp, sm->pairwise, z, z_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002294}
2295
2296
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002297#ifdef CONFIG_FILS
2298
2299int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002300 size_t pmk_len, const u8 *snonce, const u8 *anonce,
2301 const u8 *dhss, size_t dhss_len,
2302 struct wpabuf *g_sta, struct wpabuf *g_ap)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002303{
2304 u8 ick[FILS_ICK_MAX_LEN];
2305 size_t ick_len;
2306 int res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002307 u8 fils_ft[FILS_FT_MAX_LEN];
2308 size_t fils_ft_len = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002309
2310 res = fils_pmk_to_ptk(pmk, pmk_len, sm->addr, sm->wpa_auth->addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002311 snonce, anonce, dhss, dhss_len,
2312 &sm->PTK, ick, &ick_len,
2313 sm->wpa_key_mgmt, sm->pairwise,
2314 fils_ft, &fils_ft_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002315 if (res < 0)
2316 return res;
Hai Shalome21d4e82020-04-29 16:34:06 -07002317 sm->PTK_valid = true;
2318 sm->tk_already_set = false;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002319
2320#ifdef CONFIG_IEEE80211R_AP
2321 if (fils_ft_len) {
2322 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
2323 struct wpa_auth_config *conf = &wpa_auth->conf;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002324 u8 pmk_r0[PMK_LEN_MAX], pmk_r0_name[WPA_PMK_NAME_LEN];
2325 int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002326
2327 if (wpa_derive_pmk_r0(fils_ft, fils_ft_len,
2328 conf->ssid, conf->ssid_len,
2329 conf->mobility_domain,
2330 conf->r0_key_holder,
2331 conf->r0_key_holder_len,
Roshan Pius3a1667e2018-07-03 15:17:14 -07002332 sm->addr, pmk_r0, pmk_r0_name,
2333 use_sha384) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002334 return -1;
2335
Roshan Pius3a1667e2018-07-03 15:17:14 -07002336 wpa_ft_store_pmk_fils(sm, pmk_r0, pmk_r0_name);
Hai Shalom81f62d82019-07-22 12:10:00 -07002337 forced_memzero(fils_ft, sizeof(fils_ft));
Hai Shalom021b0b52019-04-10 11:17:58 -07002338
2339 res = wpa_derive_pmk_r1_name(pmk_r0_name, conf->r1_key_holder,
2340 sm->addr, sm->pmk_r1_name,
2341 use_sha384);
Hai Shalom81f62d82019-07-22 12:10:00 -07002342 forced_memzero(pmk_r0, PMK_LEN_MAX);
Hai Shalom021b0b52019-04-10 11:17:58 -07002343 if (res < 0)
2344 return -1;
2345 wpa_hexdump(MSG_DEBUG, "FILS+FT: PMKR1Name", sm->pmk_r1_name,
2346 WPA_PMK_NAME_LEN);
2347 sm->pmk_r1_name_valid = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002348 }
2349#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002350
2351 res = fils_key_auth_sk(ick, ick_len, snonce, anonce,
2352 sm->addr, sm->wpa_auth->addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002353 g_sta ? wpabuf_head(g_sta) : NULL,
2354 g_sta ? wpabuf_len(g_sta) : 0,
2355 g_ap ? wpabuf_head(g_ap) : NULL,
2356 g_ap ? wpabuf_len(g_ap) : 0,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002357 sm->wpa_key_mgmt, sm->fils_key_auth_sta,
2358 sm->fils_key_auth_ap,
2359 &sm->fils_key_auth_len);
Hai Shalom81f62d82019-07-22 12:10:00 -07002360 forced_memzero(ick, sizeof(ick));
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002361
2362 /* Store nonces for (Re)Association Request/Response frame processing */
2363 os_memcpy(sm->SNonce, snonce, FILS_NONCE_LEN);
2364 os_memcpy(sm->ANonce, anonce, FILS_NONCE_LEN);
2365
2366 return res;
2367}
2368
2369
2370static int wpa_aead_decrypt(struct wpa_state_machine *sm, struct wpa_ptk *ptk,
2371 u8 *buf, size_t buf_len, u16 *_key_data_len)
2372{
2373 struct ieee802_1x_hdr *hdr;
2374 struct wpa_eapol_key *key;
2375 u8 *pos;
2376 u16 key_data_len;
2377 u8 *tmp;
2378 const u8 *aad[1];
2379 size_t aad_len[1];
2380
2381 hdr = (struct ieee802_1x_hdr *) buf;
2382 key = (struct wpa_eapol_key *) (hdr + 1);
2383 pos = (u8 *) (key + 1);
2384 key_data_len = WPA_GET_BE16(pos);
2385 if (key_data_len < AES_BLOCK_SIZE ||
2386 key_data_len > buf_len - sizeof(*hdr) - sizeof(*key) - 2) {
2387 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO,
2388 "No room for AES-SIV data in the frame");
2389 return -1;
2390 }
2391 pos += 2; /* Pointing at the Encrypted Key Data field */
2392
2393 tmp = os_malloc(key_data_len);
2394 if (!tmp)
2395 return -1;
2396
2397 /* AES-SIV AAD from EAPOL protocol version field (inclusive) to
2398 * to Key Data (exclusive). */
2399 aad[0] = buf;
2400 aad_len[0] = pos - buf;
2401 if (aes_siv_decrypt(ptk->kek, ptk->kek_len, pos, key_data_len,
2402 1, aad, aad_len, tmp) < 0) {
2403 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO,
2404 "Invalid AES-SIV data in the frame");
2405 bin_clear_free(tmp, key_data_len);
2406 return -1;
2407 }
2408
2409 /* AEAD decryption and validation completed successfully */
2410 key_data_len -= AES_BLOCK_SIZE;
2411 wpa_hexdump_key(MSG_DEBUG, "WPA: Decrypted Key Data",
2412 tmp, key_data_len);
2413
2414 /* Replace Key Data field with the decrypted version */
2415 os_memcpy(pos, tmp, key_data_len);
2416 pos -= 2; /* Key Data Length field */
2417 WPA_PUT_BE16(pos, key_data_len);
2418 bin_clear_free(tmp, key_data_len);
2419 if (_key_data_len)
2420 *_key_data_len = key_data_len;
2421 return 0;
2422}
2423
2424
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002425const u8 * wpa_fils_validate_fils_session(struct wpa_state_machine *sm,
2426 const u8 *ies, size_t ies_len,
2427 const u8 *fils_session)
2428{
2429 const u8 *ie, *end;
2430 const u8 *session = NULL;
2431
2432 if (!wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
2433 wpa_printf(MSG_DEBUG,
2434 "FILS: Not a FILS AKM - reject association");
2435 return NULL;
2436 }
2437
2438 /* Verify Session element */
2439 ie = ies;
2440 end = ((const u8 *) ie) + ies_len;
2441 while (ie + 1 < end) {
2442 if (ie + 2 + ie[1] > end)
2443 break;
2444 if (ie[0] == WLAN_EID_EXTENSION &&
2445 ie[1] >= 1 + FILS_SESSION_LEN &&
2446 ie[2] == WLAN_EID_EXT_FILS_SESSION) {
2447 session = ie;
2448 break;
2449 }
2450 ie += 2 + ie[1];
2451 }
2452
2453 if (!session) {
2454 wpa_printf(MSG_DEBUG,
2455 "FILS: %s: Could not find FILS Session element in Assoc Req - reject",
2456 __func__);
2457 return NULL;
2458 }
2459
2460 if (!fils_session) {
2461 wpa_printf(MSG_DEBUG,
2462 "FILS: %s: Could not find FILS Session element in STA entry - reject",
2463 __func__);
2464 return NULL;
2465 }
2466
2467 if (os_memcmp(fils_session, session + 3, FILS_SESSION_LEN) != 0) {
2468 wpa_printf(MSG_DEBUG, "FILS: Session mismatch");
2469 wpa_hexdump(MSG_DEBUG, "FILS: Expected FILS Session",
2470 fils_session, FILS_SESSION_LEN);
2471 wpa_hexdump(MSG_DEBUG, "FILS: Received FILS Session",
2472 session + 3, FILS_SESSION_LEN);
2473 return NULL;
2474 }
2475 return session;
2476}
2477
2478
2479int wpa_fils_validate_key_confirm(struct wpa_state_machine *sm, const u8 *ies,
2480 size_t ies_len)
2481{
2482 struct ieee802_11_elems elems;
2483
2484 if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed) {
2485 wpa_printf(MSG_DEBUG,
2486 "FILS: Failed to parse decrypted elements");
2487 return -1;
2488 }
2489
2490 if (!elems.fils_session) {
2491 wpa_printf(MSG_DEBUG, "FILS: No FILS Session element");
2492 return -1;
2493 }
2494
2495 if (!elems.fils_key_confirm) {
2496 wpa_printf(MSG_DEBUG, "FILS: No FILS Key Confirm element");
2497 return -1;
2498 }
2499
2500 if (elems.fils_key_confirm_len != sm->fils_key_auth_len) {
2501 wpa_printf(MSG_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07002502 "FILS: Unexpected Key-Auth length %d (expected %zu)",
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002503 elems.fils_key_confirm_len,
Hai Shalomfdcde762020-04-02 11:19:20 -07002504 sm->fils_key_auth_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002505 return -1;
2506 }
2507
2508 if (os_memcmp(elems.fils_key_confirm, sm->fils_key_auth_sta,
2509 sm->fils_key_auth_len) != 0) {
2510 wpa_printf(MSG_DEBUG, "FILS: Key-Auth mismatch");
2511 wpa_hexdump(MSG_DEBUG, "FILS: Received Key-Auth",
2512 elems.fils_key_confirm, elems.fils_key_confirm_len);
2513 wpa_hexdump(MSG_DEBUG, "FILS: Expected Key-Auth",
2514 sm->fils_key_auth_sta, sm->fils_key_auth_len);
2515 return -1;
2516 }
2517
2518 return 0;
2519}
2520
2521
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002522int fils_decrypt_assoc(struct wpa_state_machine *sm, const u8 *fils_session,
2523 const struct ieee80211_mgmt *mgmt, size_t frame_len,
2524 u8 *pos, size_t left)
2525{
2526 u16 fc, stype;
2527 const u8 *end, *ie_start, *ie, *session, *crypt;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002528 const u8 *aad[5];
2529 size_t aad_len[5];
2530
2531 if (!sm || !sm->PTK_valid) {
2532 wpa_printf(MSG_DEBUG,
2533 "FILS: No KEK to decrypt Assocication Request frame");
2534 return -1;
2535 }
2536
2537 if (!wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
2538 wpa_printf(MSG_DEBUG,
2539 "FILS: Not a FILS AKM - reject association");
2540 return -1;
2541 }
2542
2543 end = ((const u8 *) mgmt) + frame_len;
2544 fc = le_to_host16(mgmt->frame_control);
2545 stype = WLAN_FC_GET_STYPE(fc);
2546 if (stype == WLAN_FC_STYPE_REASSOC_REQ)
2547 ie_start = mgmt->u.reassoc_req.variable;
2548 else
2549 ie_start = mgmt->u.assoc_req.variable;
2550 ie = ie_start;
2551
2552 /*
2553 * Find FILS Session element which is the last unencrypted element in
2554 * the frame.
2555 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002556 session = wpa_fils_validate_fils_session(sm, ie, end - ie,
2557 fils_session);
2558 if (!session) {
2559 wpa_printf(MSG_DEBUG, "FILS: Session validation failed");
2560 return -1;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002561 }
2562
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002563 crypt = session + 2 + session[1];
2564
2565 if (end - crypt < AES_BLOCK_SIZE) {
2566 wpa_printf(MSG_DEBUG,
2567 "FILS: Too short frame to include AES-SIV data");
2568 return -1;
2569 }
2570
2571 /* AES-SIV AAD vectors */
2572
2573 /* The STA's MAC address */
2574 aad[0] = mgmt->sa;
2575 aad_len[0] = ETH_ALEN;
2576 /* The AP's BSSID */
2577 aad[1] = mgmt->da;
2578 aad_len[1] = ETH_ALEN;
2579 /* The STA's nonce */
2580 aad[2] = sm->SNonce;
2581 aad_len[2] = FILS_NONCE_LEN;
2582 /* The AP's nonce */
2583 aad[3] = sm->ANonce;
2584 aad_len[3] = FILS_NONCE_LEN;
2585 /*
2586 * The (Re)Association Request frame from the Capability Information
2587 * field to the FILS Session element (both inclusive).
2588 */
2589 aad[4] = (const u8 *) &mgmt->u.assoc_req.capab_info;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002590 aad_len[4] = crypt - aad[4];
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002591
2592 if (aes_siv_decrypt(sm->PTK.kek, sm->PTK.kek_len, crypt, end - crypt,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002593 5, aad, aad_len, pos + (crypt - ie_start)) < 0) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002594 wpa_printf(MSG_DEBUG,
2595 "FILS: Invalid AES-SIV data in the frame");
2596 return -1;
2597 }
2598 wpa_hexdump(MSG_DEBUG, "FILS: Decrypted Association Request elements",
2599 pos, left - AES_BLOCK_SIZE);
2600
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002601 if (wpa_fils_validate_key_confirm(sm, pos, left - AES_BLOCK_SIZE) < 0) {
2602 wpa_printf(MSG_DEBUG, "FILS: Key Confirm validation failed");
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002603 return -1;
2604 }
2605
2606 return left - AES_BLOCK_SIZE;
2607}
2608
2609
2610int fils_encrypt_assoc(struct wpa_state_machine *sm, u8 *buf,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002611 size_t current_len, size_t max_len,
2612 const struct wpabuf *hlp)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002613{
2614 u8 *end = buf + max_len;
2615 u8 *pos = buf + current_len;
2616 struct ieee80211_mgmt *mgmt;
2617 struct wpabuf *plain;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002618 const u8 *aad[5];
2619 size_t aad_len[5];
2620
2621 if (!sm || !sm->PTK_valid)
2622 return -1;
2623
2624 wpa_hexdump(MSG_DEBUG,
2625 "FILS: Association Response frame before FILS processing",
2626 buf, current_len);
2627
2628 mgmt = (struct ieee80211_mgmt *) buf;
2629
2630 /* AES-SIV AAD vectors */
2631
2632 /* The AP's BSSID */
2633 aad[0] = mgmt->sa;
2634 aad_len[0] = ETH_ALEN;
2635 /* The STA's MAC address */
2636 aad[1] = mgmt->da;
2637 aad_len[1] = ETH_ALEN;
2638 /* The AP's nonce */
2639 aad[2] = sm->ANonce;
2640 aad_len[2] = FILS_NONCE_LEN;
2641 /* The STA's nonce */
2642 aad[3] = sm->SNonce;
2643 aad_len[3] = FILS_NONCE_LEN;
2644 /*
2645 * The (Re)Association Response frame from the Capability Information
2646 * field (the same offset in both Association and Reassociation
2647 * Response frames) to the FILS Session element (both inclusive).
2648 */
2649 aad[4] = (const u8 *) &mgmt->u.assoc_resp.capab_info;
2650 aad_len[4] = pos - aad[4];
2651
2652 /* The following elements will be encrypted with AES-SIV */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002653 plain = fils_prepare_plainbuf(sm, hlp);
2654 if (!plain) {
2655 wpa_printf(MSG_DEBUG, "FILS: Plain buffer prep failed");
2656 return -1;
2657 }
2658
2659 if (pos + wpabuf_len(plain) + AES_BLOCK_SIZE > end) {
2660 wpa_printf(MSG_DEBUG,
2661 "FILS: Not enough room for FILS elements");
Hai Shalom81f62d82019-07-22 12:10:00 -07002662 wpabuf_clear_free(plain);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002663 return -1;
2664 }
2665
2666 wpa_hexdump_buf_key(MSG_DEBUG, "FILS: Association Response plaintext",
2667 plain);
2668
2669 if (aes_siv_encrypt(sm->PTK.kek, sm->PTK.kek_len,
2670 wpabuf_head(plain), wpabuf_len(plain),
2671 5, aad, aad_len, pos) < 0) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002672 wpabuf_clear_free(plain);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002673 return -1;
2674 }
2675
2676 wpa_hexdump(MSG_DEBUG,
2677 "FILS: Encrypted Association Response elements",
2678 pos, AES_BLOCK_SIZE + wpabuf_len(plain));
2679 current_len += wpabuf_len(plain) + AES_BLOCK_SIZE;
Hai Shalom81f62d82019-07-22 12:10:00 -07002680 wpabuf_clear_free(plain);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002681
2682 sm->fils_completed = 1;
2683
2684 return current_len;
2685}
2686
2687
2688static struct wpabuf * fils_prepare_plainbuf(struct wpa_state_machine *sm,
2689 const struct wpabuf *hlp)
2690{
2691 struct wpabuf *plain;
2692 u8 *len, *tmp, *tmp2;
2693 u8 hdr[2];
2694 u8 *gtk, dummy_gtk[32];
2695 size_t gtk_len;
2696 struct wpa_group *gsm;
Hai Shalomfdcde762020-04-02 11:19:20 -07002697 size_t plain_len;
2698 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002699
Hai Shalomfdcde762020-04-02 11:19:20 -07002700 plain_len = 1000 + ieee80211w_kde_len(sm);
2701 if (conf->transition_disable)
2702 plain_len += 2 + RSN_SELECTOR_LEN + 1;
2703 plain = wpabuf_alloc(plain_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002704 if (!plain)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002705 return NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002706
2707 /* TODO: FILS Public Key */
2708
2709 /* FILS Key Confirmation */
2710 wpabuf_put_u8(plain, WLAN_EID_EXTENSION); /* Element ID */
2711 wpabuf_put_u8(plain, 1 + sm->fils_key_auth_len); /* Length */
2712 /* Element ID Extension */
2713 wpabuf_put_u8(plain, WLAN_EID_EXT_FILS_KEY_CONFIRM);
2714 wpabuf_put_data(plain, sm->fils_key_auth_ap, sm->fils_key_auth_len);
2715
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002716 /* FILS HLP Container */
2717 if (hlp)
2718 wpabuf_put_buf(plain, hlp);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002719
2720 /* TODO: FILS IP Address Assignment */
2721
2722 /* Key Delivery */
2723 gsm = sm->group;
2724 wpabuf_put_u8(plain, WLAN_EID_EXTENSION); /* Element ID */
2725 len = wpabuf_put(plain, 1);
2726 wpabuf_put_u8(plain, WLAN_EID_EXT_KEY_DELIVERY);
2727 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN,
2728 wpabuf_put(plain, WPA_KEY_RSC_LEN));
2729 /* GTK KDE */
2730 gtk = gsm->GTK[gsm->GN - 1];
2731 gtk_len = gsm->GTK_len;
Hai Shalomfdcde762020-04-02 11:19:20 -07002732 if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002733 /*
2734 * Provide unique random GTK to each STA to prevent use
2735 * of GTK in the BSS.
2736 */
2737 if (random_get_bytes(dummy_gtk, gtk_len) < 0) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002738 wpabuf_clear_free(plain);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002739 return NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002740 }
2741 gtk = dummy_gtk;
2742 }
2743 hdr[0] = gsm->GN & 0x03;
2744 hdr[1] = 0;
2745 tmp = wpabuf_put(plain, 0);
2746 tmp2 = wpa_add_kde(tmp, RSN_KEY_DATA_GROUPKEY, hdr, 2,
2747 gtk, gtk_len);
2748 wpabuf_put(plain, tmp2 - tmp);
2749
Hai Shalomfdcde762020-04-02 11:19:20 -07002750 /* IGTK KDE and BIGTK KDE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002751 tmp = wpabuf_put(plain, 0);
2752 tmp2 = ieee80211w_kde_add(sm, tmp);
2753 wpabuf_put(plain, tmp2 - tmp);
2754
Hai Shalomfdcde762020-04-02 11:19:20 -07002755 if (conf->transition_disable) {
2756 tmp = wpabuf_put(plain, 0);
2757 tmp2 = wpa_add_kde(tmp, WFA_KEY_DATA_TRANSITION_DISABLE,
2758 &conf->transition_disable, 1, NULL, 0);
2759 wpabuf_put(plain, tmp2 - tmp);
2760 }
2761
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002762 *len = (u8 *) wpabuf_put(plain, 0) - len - 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08002763
2764#ifdef CONFIG_OCV
2765 if (wpa_auth_uses_ocv(sm)) {
2766 struct wpa_channel_info ci;
2767 u8 *pos;
2768
2769 if (wpa_channel_info(sm->wpa_auth, &ci) != 0) {
2770 wpa_printf(MSG_WARNING,
2771 "FILS: Failed to get channel info for OCI element");
Hai Shalom81f62d82019-07-22 12:10:00 -07002772 wpabuf_clear_free(plain);
Hai Shalom74f70d42019-02-11 14:42:39 -08002773 return NULL;
2774 }
Hai Shalom899fcc72020-10-19 14:38:18 -07002775#ifdef CONFIG_TESTING_OPTIONS
2776 if (conf->oci_freq_override_fils_assoc) {
2777 wpa_printf(MSG_INFO,
2778 "TEST: Override OCI frequency %d -> %u MHz",
2779 ci.frequency,
2780 conf->oci_freq_override_fils_assoc);
2781 ci.frequency = conf->oci_freq_override_fils_assoc;
2782 }
2783#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom74f70d42019-02-11 14:42:39 -08002784
2785 pos = wpabuf_put(plain, OCV_OCI_EXTENDED_LEN);
2786 if (ocv_insert_extended_oci(&ci, pos) < 0) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002787 wpabuf_clear_free(plain);
Hai Shalom74f70d42019-02-11 14:42:39 -08002788 return NULL;
2789 }
2790 }
2791#endif /* CONFIG_OCV */
2792
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002793 return plain;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002794}
2795
2796
2797int fils_set_tk(struct wpa_state_machine *sm)
2798{
2799 enum wpa_alg alg;
2800 int klen;
2801
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002802 if (!sm || !sm->PTK_valid) {
2803 wpa_printf(MSG_DEBUG, "FILS: No valid PTK available to set TK");
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002804 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002805 }
2806 if (sm->tk_already_set) {
2807 wpa_printf(MSG_DEBUG, "FILS: TK already set to the driver");
2808 return -1;
2809 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002810
2811 alg = wpa_cipher_to_alg(sm->pairwise);
2812 klen = wpa_cipher_key_len(sm->pairwise);
2813
2814 wpa_printf(MSG_DEBUG, "FILS: Configure TK to the driver");
2815 if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0,
Hai Shalomfdcde762020-04-02 11:19:20 -07002816 sm->PTK.tk, klen, KEY_FLAG_PAIRWISE_RX_TX)) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002817 wpa_printf(MSG_DEBUG, "FILS: Failed to set TK to the driver");
2818 return -1;
2819 }
Hai Shalome21d4e82020-04-29 16:34:06 -07002820 sm->tk_already_set = true;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002821
2822 return 0;
2823}
2824
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002825
2826u8 * hostapd_eid_assoc_fils_session(struct wpa_state_machine *sm, u8 *buf,
2827 const u8 *fils_session, struct wpabuf *hlp)
2828{
2829 struct wpabuf *plain;
2830 u8 *pos = buf;
2831
2832 /* FILS Session */
2833 *pos++ = WLAN_EID_EXTENSION; /* Element ID */
2834 *pos++ = 1 + FILS_SESSION_LEN; /* Length */
2835 *pos++ = WLAN_EID_EXT_FILS_SESSION; /* Element ID Extension */
2836 os_memcpy(pos, fils_session, FILS_SESSION_LEN);
2837 pos += FILS_SESSION_LEN;
2838
2839 plain = fils_prepare_plainbuf(sm, hlp);
2840 if (!plain) {
2841 wpa_printf(MSG_DEBUG, "FILS: Plain buffer prep failed");
2842 return NULL;
2843 }
2844
2845 os_memcpy(pos, wpabuf_head(plain), wpabuf_len(plain));
2846 pos += wpabuf_len(plain);
2847
Hai Shalomfdcde762020-04-02 11:19:20 -07002848 wpa_printf(MSG_DEBUG, "%s: plain buf_len: %zu", __func__,
2849 wpabuf_len(plain));
Hai Shalom81f62d82019-07-22 12:10:00 -07002850 wpabuf_clear_free(plain);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002851 sm->fils_completed = 1;
2852 return pos;
2853}
2854
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002855#endif /* CONFIG_FILS */
2856
2857
Hai Shalom74f70d42019-02-11 14:42:39 -08002858#ifdef CONFIG_OCV
2859int get_sta_tx_parameters(struct wpa_state_machine *sm, int ap_max_chanwidth,
2860 int ap_seg1_idx, int *bandwidth, int *seg1_idx)
2861{
2862 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
2863
2864 if (!wpa_auth->cb->get_sta_tx_params)
2865 return -1;
2866 return wpa_auth->cb->get_sta_tx_params(wpa_auth->cb_ctx, sm->addr,
2867 ap_max_chanwidth, ap_seg1_idx,
2868 bandwidth, seg1_idx);
2869}
2870#endif /* CONFIG_OCV */
2871
2872
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002873SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
2874{
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002875 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002876 struct wpa_ptk PTK;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07002877 int ok = 0, psk_found = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002878 const u8 *pmk = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002879 size_t pmk_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002880 int ft;
2881 const u8 *eapol_key_ie, *key_data, *mic;
2882 u16 key_data_length;
2883 size_t mic_len, eapol_key_ie_len;
2884 struct ieee802_1x_hdr *hdr;
2885 struct wpa_eapol_key *key;
2886 struct wpa_eapol_ie_parse kde;
Hai Shalom021b0b52019-04-10 11:17:58 -07002887 int vlan_id = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002888 int owe_ptk_workaround = !!wpa_auth->conf.owe_ptk_workaround;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002889
2890 SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07002891 sm->EAPOLKeyReceived = false;
2892 sm->update_snonce = false;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002893 os_memset(&PTK, 0, sizeof(PTK));
2894
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002895 mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002896
2897 /* WPA with IEEE 802.1X: use the derived PMK from EAP
2898 * WPA-PSK: iterate through possible PSKs and select the one matching
2899 * the packet */
2900 for (;;) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002901 if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
2902 !wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002903 pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr,
Hai Shalom021b0b52019-04-10 11:17:58 -07002904 sm->p2p_dev_addr, pmk, &pmk_len,
2905 &vlan_id);
Hai Shalomfdcde762020-04-02 11:19:20 -07002906 if (!pmk)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002907 break;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07002908 psk_found = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002909#ifdef CONFIG_IEEE80211R_AP
2910 if (wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) {
2911 os_memcpy(sm->xxkey, pmk, pmk_len);
2912 sm->xxkey_len = pmk_len;
2913 }
2914#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002915 } else {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002916 pmk = sm->PMK;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002917 pmk_len = sm->pmk_len;
2918 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002919
Hai Shalom81f62d82019-07-22 12:10:00 -07002920 if ((!pmk || !pmk_len) && sm->pmksa) {
2921 wpa_printf(MSG_DEBUG, "WPA: Use PMK from PMKSA cache");
2922 pmk = sm->pmksa->pmk;
2923 pmk_len = sm->pmksa->pmk_len;
2924 }
2925
Hai Shalomfdcde762020-04-02 11:19:20 -07002926 if (wpa_derive_ptk(sm, sm->SNonce, pmk, pmk_len, &PTK,
2927 owe_ptk_workaround == 2) < 0)
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002928 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002929
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002930 if (mic_len &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002931 wpa_verify_key_mic(sm->wpa_key_mgmt, pmk_len, &PTK,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002932 sm->last_rx_eapol_key,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002933 sm->last_rx_eapol_key_len) == 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07002934 if (sm->PMK != pmk) {
2935 os_memcpy(sm->PMK, pmk, pmk_len);
2936 sm->pmk_len = pmk_len;
2937 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002938 ok = 1;
2939 break;
2940 }
2941
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002942#ifdef CONFIG_FILS
2943 if (!mic_len &&
2944 wpa_aead_decrypt(sm, &PTK, sm->last_rx_eapol_key,
2945 sm->last_rx_eapol_key_len, NULL) == 0) {
2946 ok = 1;
2947 break;
2948 }
2949#endif /* CONFIG_FILS */
2950
Hai Shalomfdcde762020-04-02 11:19:20 -07002951#ifdef CONFIG_OWE
2952 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE && pmk_len > 32 &&
2953 owe_ptk_workaround == 1) {
2954 wpa_printf(MSG_DEBUG,
2955 "OWE: Try PTK derivation workaround with SHA256");
2956 owe_ptk_workaround = 2;
2957 continue;
2958 }
2959#endif /* CONFIG_OWE */
2960
Roshan Pius3a1667e2018-07-03 15:17:14 -07002961 if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
2962 wpa_key_mgmt_sae(sm->wpa_key_mgmt))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002963 break;
2964 }
2965
2966 if (!ok) {
2967 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
2968 "invalid MIC in msg 2/4 of 4-Way Handshake");
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07002969 if (psk_found)
2970 wpa_auth_psk_failure_report(sm->wpa_auth, sm->addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002971 return;
2972 }
2973
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002974 /*
2975 * Note: last_rx_eapol_key length fields have already been validated in
2976 * wpa_receive().
2977 */
2978 hdr = (struct ieee802_1x_hdr *) sm->last_rx_eapol_key;
2979 key = (struct wpa_eapol_key *) (hdr + 1);
2980 mic = (u8 *) (key + 1);
2981 key_data = mic + mic_len + 2;
2982 key_data_length = WPA_GET_BE16(mic + mic_len);
2983 if (key_data_length > sm->last_rx_eapol_key_len - sizeof(*hdr) -
2984 sizeof(*key) - mic_len - 2)
2985 return;
2986
2987 if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) {
2988 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
2989 "received EAPOL-Key msg 2/4 with invalid Key Data contents");
2990 return;
2991 }
2992 if (kde.rsn_ie) {
2993 eapol_key_ie = kde.rsn_ie;
2994 eapol_key_ie_len = kde.rsn_ie_len;
2995 } else if (kde.osen) {
2996 eapol_key_ie = kde.osen;
2997 eapol_key_ie_len = kde.osen_len;
2998 } else {
2999 eapol_key_ie = kde.wpa_ie;
3000 eapol_key_ie_len = kde.wpa_ie_len;
3001 }
3002 ft = sm->wpa == WPA_VERSION_WPA2 && wpa_key_mgmt_ft(sm->wpa_key_mgmt);
Hai Shalomfdcde762020-04-02 11:19:20 -07003003 if (!sm->wpa_ie ||
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003004 wpa_compare_rsn_ie(ft, sm->wpa_ie, sm->wpa_ie_len,
3005 eapol_key_ie, eapol_key_ie_len)) {
3006 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
3007 "WPA IE from (Re)AssocReq did not match with msg 2/4");
3008 if (sm->wpa_ie) {
3009 wpa_hexdump(MSG_DEBUG, "WPA IE in AssocReq",
3010 sm->wpa_ie, sm->wpa_ie_len);
3011 }
3012 wpa_hexdump(MSG_DEBUG, "WPA IE in msg 2/4",
3013 eapol_key_ie, eapol_key_ie_len);
3014 /* MLME-DEAUTHENTICATE.request */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003015 wpa_sta_disconnect(wpa_auth, sm->addr,
3016 WLAN_REASON_PREV_AUTH_NOT_VALID);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003017 return;
3018 }
Hai Shalomc3565922019-10-28 11:58:20 -07003019 if ((!sm->rsnxe && kde.rsnxe) ||
3020 (sm->rsnxe && !kde.rsnxe) ||
3021 (sm->rsnxe && kde.rsnxe &&
3022 (sm->rsnxe_len != kde.rsnxe_len ||
3023 os_memcmp(sm->rsnxe, kde.rsnxe, sm->rsnxe_len) != 0))) {
3024 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
3025 "RSNXE from (Re)AssocReq did not match the one in EAPOL-Key msg 2/4");
3026 wpa_hexdump(MSG_DEBUG, "RSNXE in AssocReq",
3027 sm->rsnxe, sm->rsnxe_len);
3028 wpa_hexdump(MSG_DEBUG, "RSNXE in EAPOL-Key msg 2/4",
3029 kde.rsnxe, kde.rsnxe_len);
3030 /* MLME-DEAUTHENTICATE.request */
3031 wpa_sta_disconnect(wpa_auth, sm->addr,
3032 WLAN_REASON_PREV_AUTH_NOT_VALID);
3033 return;
3034 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003035#ifdef CONFIG_OCV
3036 if (wpa_auth_uses_ocv(sm)) {
3037 struct wpa_channel_info ci;
3038 int tx_chanwidth;
3039 int tx_seg1_idx;
Hai Shalom899fcc72020-10-19 14:38:18 -07003040 enum oci_verify_result res;
Hai Shalom74f70d42019-02-11 14:42:39 -08003041
3042 if (wpa_channel_info(wpa_auth, &ci) != 0) {
3043 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
3044 "Failed to get channel info to validate received OCI in EAPOL-Key 2/4");
3045 return;
3046 }
3047
3048 if (get_sta_tx_parameters(sm,
3049 channel_width_to_int(ci.chanwidth),
3050 ci.seg1_idx, &tx_chanwidth,
3051 &tx_seg1_idx) < 0)
3052 return;
3053
Hai Shalom899fcc72020-10-19 14:38:18 -07003054 res = ocv_verify_tx_params(kde.oci, kde.oci_len, &ci,
3055 tx_chanwidth, tx_seg1_idx);
3056 if (wpa_auth_uses_ocv(sm) == 2 && res == OCI_NOT_FOUND) {
3057 /* Work around misbehaving STAs */
3058 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
3059 "Disable OCV with a STA that does not send OCI");
3060 wpa_auth_set_ocv(sm, 0);
3061 } else if (res != OCI_SUCCESS) {
3062 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
3063 "OCV failed: %s", ocv_errorstr);
3064 if (wpa_auth->conf.msg_ctx)
3065 wpa_msg(wpa_auth->conf.msg_ctx, MSG_INFO,
3066 OCV_FAILURE "addr=" MACSTR
3067 " frame=eapol-key-m2 error=%s",
3068 MAC2STR(sm->addr), ocv_errorstr);
Hai Shalom74f70d42019-02-11 14:42:39 -08003069 return;
3070 }
3071 }
3072#endif /* CONFIG_OCV */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003073#ifdef CONFIG_IEEE80211R_AP
3074 if (ft && ft_check_msg_2_of_4(wpa_auth, sm, &kde) < 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003075 wpa_sta_disconnect(wpa_auth, sm->addr,
3076 WLAN_REASON_PREV_AUTH_NOT_VALID);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003077 return;
3078 }
3079#endif /* CONFIG_IEEE80211R_AP */
3080#ifdef CONFIG_P2P
3081 if (kde.ip_addr_req && kde.ip_addr_req[0] &&
3082 wpa_auth->ip_pool && WPA_GET_BE32(sm->ip_addr) == 0) {
3083 int idx;
3084 wpa_printf(MSG_DEBUG,
3085 "P2P: IP address requested in EAPOL-Key exchange");
3086 idx = bitfield_get_first_zero(wpa_auth->ip_pool);
3087 if (idx >= 0) {
3088 u32 start = WPA_GET_BE32(wpa_auth->conf.ip_addr_start);
3089 bitfield_set(wpa_auth->ip_pool, idx);
3090 WPA_PUT_BE32(sm->ip_addr, start + idx);
3091 wpa_printf(MSG_DEBUG,
3092 "P2P: Assigned IP address %u.%u.%u.%u to "
3093 MACSTR, sm->ip_addr[0], sm->ip_addr[1],
3094 sm->ip_addr[2], sm->ip_addr[3],
3095 MAC2STR(sm->addr));
3096 }
3097 }
3098#endif /* CONFIG_P2P */
3099
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003100#ifdef CONFIG_DPP2
3101 if (DPP_VERSION > 1 && kde.dpp_kde) {
3102 wpa_printf(MSG_DEBUG,
3103 "DPP: peer Protocol Version %u Flags 0x%x",
3104 kde.dpp_kde[0], kde.dpp_kde[1]);
3105 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP &&
3106 wpa_auth->conf.dpp_pfs != 2 &&
3107 (kde.dpp_kde[1] & DPP_KDE_PFS_ALLOWED) &&
3108 !sm->dpp_z) {
3109 wpa_printf(MSG_INFO,
3110 "DPP: Peer indicated it supports PFS and local configuration allows this, but PFS was not negotiated for the association");
3111 wpa_sta_disconnect(wpa_auth, sm->addr,
3112 WLAN_REASON_PREV_AUTH_NOT_VALID);
3113 return;
3114 }
3115 }
3116#endif /* CONFIG_DPP2 */
3117
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003118#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003119 if (sm->wpa == WPA_VERSION_WPA2 && wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
3120 /*
3121 * Verify that PMKR1Name from EAPOL-Key message 2/4 matches
3122 * with the value we derived.
3123 */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003124 if (os_memcmp_const(sm->sup_pmk_r1_name, sm->pmk_r1_name,
3125 WPA_PMK_NAME_LEN) != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003126 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07003127 "PMKR1Name mismatch in FT 4-way handshake");
3128 wpa_hexdump(MSG_DEBUG,
3129 "FT: PMKR1Name from Supplicant",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003130 sm->sup_pmk_r1_name, WPA_PMK_NAME_LEN);
3131 wpa_hexdump(MSG_DEBUG, "FT: Derived PMKR1Name",
3132 sm->pmk_r1_name, WPA_PMK_NAME_LEN);
3133 return;
3134 }
3135 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003136#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003137
Hai Shalom021b0b52019-04-10 11:17:58 -07003138 if (vlan_id && wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
3139 wpa_auth_update_vlan(wpa_auth, sm->addr, vlan_id) < 0) {
3140 wpa_sta_disconnect(wpa_auth, sm->addr,
3141 WLAN_REASON_PREV_AUTH_NOT_VALID);
3142 return;
3143 }
3144
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003145 sm->pending_1_of_4_timeout = 0;
3146 eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm);
3147
3148 if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) {
3149 /* PSK may have changed from the previous choice, so update
3150 * state machine data based on whatever PSK was selected here.
3151 */
3152 os_memcpy(sm->PMK, pmk, PMK_LEN);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003153 sm->pmk_len = PMK_LEN;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003154 }
3155
Hai Shalome21d4e82020-04-29 16:34:06 -07003156 sm->MICVerified = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003157
3158 os_memcpy(&sm->PTK, &PTK, sizeof(PTK));
Hai Shalom81f62d82019-07-22 12:10:00 -07003159 forced_memzero(&PTK, sizeof(PTK));
Hai Shalome21d4e82020-04-29 16:34:06 -07003160 sm->PTK_valid = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003161}
3162
3163
3164SM_STATE(WPA_PTK, PTKCALCNEGOTIATING2)
3165{
3166 SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING2, wpa_ptk);
3167 sm->TimeoutCtr = 0;
3168}
3169
3170
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003171static int ieee80211w_kde_len(struct wpa_state_machine *sm)
3172{
Hai Shalomfdcde762020-04-02 11:19:20 -07003173 size_t len = 0;
3174
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003175 if (sm->mgmt_frame_prot) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003176 len += 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN;
3177 len += wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
3178 }
3179 if (sm->mgmt_frame_prot && sm->wpa_auth->conf.beacon_prot) {
3180 len += 2 + RSN_SELECTOR_LEN + WPA_BIGTK_KDE_PREFIX_LEN;
3181 len += wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003182 }
3183
Hai Shalomfdcde762020-04-02 11:19:20 -07003184 return len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003185}
3186
3187
3188static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos)
3189{
3190 struct wpa_igtk_kde igtk;
Hai Shalomfdcde762020-04-02 11:19:20 -07003191 struct wpa_bigtk_kde bigtk;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003192 struct wpa_group *gsm = sm->group;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003193 u8 rsc[WPA_KEY_RSC_LEN];
Hai Shalomfdcde762020-04-02 11:19:20 -07003194 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
3195 size_t len = wpa_cipher_key_len(conf->group_mgmt_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003196
3197 if (!sm->mgmt_frame_prot)
3198 return pos;
3199
3200 igtk.keyid[0] = gsm->GN_igtk;
3201 igtk.keyid[1] = 0;
3202 if (gsm->wpa_group_state != WPA_GROUP_SETKEYSDONE ||
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003203 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, rsc) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003204 os_memset(igtk.pn, 0, sizeof(igtk.pn));
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003205 else
3206 os_memcpy(igtk.pn, rsc, sizeof(igtk.pn));
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003207 os_memcpy(igtk.igtk, gsm->IGTK[gsm->GN_igtk - 4], len);
Hai Shalomfdcde762020-04-02 11:19:20 -07003208 if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003209 /*
3210 * Provide unique random IGTK to each STA to prevent use of
3211 * IGTK in the BSS.
3212 */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003213 if (random_get_bytes(igtk.igtk, len) < 0)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003214 return pos;
3215 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003216 pos = wpa_add_kde(pos, RSN_KEY_DATA_IGTK,
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003217 (const u8 *) &igtk, WPA_IGTK_KDE_PREFIX_LEN + len,
3218 NULL, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003219
Hai Shalomfdcde762020-04-02 11:19:20 -07003220 if (!conf->beacon_prot)
3221 return pos;
3222
3223 bigtk.keyid[0] = gsm->GN_bigtk;
3224 bigtk.keyid[1] = 0;
3225 if (gsm->wpa_group_state != WPA_GROUP_SETKEYSDONE ||
3226 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_bigtk, rsc) < 0)
3227 os_memset(bigtk.pn, 0, sizeof(bigtk.pn));
3228 else
3229 os_memcpy(bigtk.pn, rsc, sizeof(bigtk.pn));
3230 os_memcpy(bigtk.bigtk, gsm->BIGTK[gsm->GN_bigtk - 6], len);
Hai Shalom899fcc72020-10-19 14:38:18 -07003231 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
3232 /*
3233 * Provide unique random BIGTK to each OSEN STA to prevent use
3234 * of BIGTK in the BSS.
3235 */
3236 if (random_get_bytes(bigtk.bigtk, len) < 0)
3237 return pos;
3238 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003239 pos = wpa_add_kde(pos, RSN_KEY_DATA_BIGTK,
3240 (const u8 *) &bigtk, WPA_BIGTK_KDE_PREFIX_LEN + len,
3241 NULL, 0);
3242
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003243 return pos;
3244}
3245
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003246
Hai Shalom74f70d42019-02-11 14:42:39 -08003247static int ocv_oci_len(struct wpa_state_machine *sm)
3248{
3249#ifdef CONFIG_OCV
3250 if (wpa_auth_uses_ocv(sm))
3251 return OCV_OCI_KDE_LEN;
3252#endif /* CONFIG_OCV */
3253 return 0;
3254}
3255
Hai Shalom899fcc72020-10-19 14:38:18 -07003256
3257static int ocv_oci_add(struct wpa_state_machine *sm, u8 **argpos,
3258 unsigned int freq)
Hai Shalom74f70d42019-02-11 14:42:39 -08003259{
3260#ifdef CONFIG_OCV
3261 struct wpa_channel_info ci;
3262
3263 if (!wpa_auth_uses_ocv(sm))
3264 return 0;
3265
3266 if (wpa_channel_info(sm->wpa_auth, &ci) != 0) {
3267 wpa_printf(MSG_WARNING,
3268 "Failed to get channel info for OCI element");
3269 return -1;
3270 }
Hai Shalom899fcc72020-10-19 14:38:18 -07003271#ifdef CONFIG_TESTING_OPTIONS
3272 if (freq) {
3273 wpa_printf(MSG_INFO,
3274 "TEST: Override OCI KDE frequency %d -> %u MHz",
3275 ci.frequency, freq);
3276 ci.frequency = freq;
3277 }
3278#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom74f70d42019-02-11 14:42:39 -08003279
3280 return ocv_insert_oci_kde(&ci, argpos);
3281#else /* CONFIG_OCV */
3282 return 0;
3283#endif /* CONFIG_OCV */
3284}
3285
3286
Hai Shalomfdcde762020-04-02 11:19:20 -07003287#ifdef CONFIG_TESTING_OPTIONS
3288static u8 * replace_ie(const char *name, const u8 *old_buf, size_t *len, u8 eid,
3289 const u8 *ie, size_t ie_len)
3290{
3291 const u8 *elem;
3292 u8 *buf;
3293
3294 wpa_printf(MSG_DEBUG, "TESTING: %s EAPOL override", name);
3295 wpa_hexdump(MSG_DEBUG, "TESTING: wpa_ie before override",
3296 old_buf, *len);
3297 buf = os_malloc(*len + ie_len);
3298 if (!buf)
3299 return NULL;
3300 os_memcpy(buf, old_buf, *len);
3301 elem = get_ie(buf, *len, eid);
3302 if (elem) {
3303 u8 elem_len = 2 + elem[1];
3304
3305 os_memmove((void *) elem, elem + elem_len,
3306 *len - (elem - buf) - elem_len);
3307 *len -= elem_len;
3308 }
3309 os_memcpy(buf + *len, ie, ie_len);
3310 *len += ie_len;
3311 wpa_hexdump(MSG_DEBUG, "TESTING: wpa_ie after EAPOL override",
3312 buf, *len);
3313
3314 return buf;
3315}
3316#endif /* CONFIG_TESTING_OPTIONS */
3317
3318
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003319SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
3320{
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003321 u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde = NULL, *pos, dummy_gtk[32];
Hai Shalomfdcde762020-04-02 11:19:20 -07003322 size_t gtk_len, kde_len, wpa_ie_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003323 struct wpa_group *gsm = sm->group;
3324 u8 *wpa_ie;
Hai Shalomfdcde762020-04-02 11:19:20 -07003325 int secure, gtkidx, encr = 0;
3326 u8 *wpa_ie_buf = NULL, *wpa_ie_buf2 = NULL;
3327 u8 hdr[2];
3328 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003329
3330 SM_ENTRY_MA(WPA_PTK, PTKINITNEGOTIATING, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07003331 sm->TimeoutEvt = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003332
3333 sm->TimeoutCtr++;
Hai Shalomfdcde762020-04-02 11:19:20 -07003334 if (conf->wpa_disable_eapol_key_retries && sm->TimeoutCtr > 1) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003335 /* Do not allow retransmission of EAPOL-Key msg 3/4 */
3336 return;
3337 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003338 if (sm->TimeoutCtr > conf->wpa_pairwise_update_count) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003339 /* No point in sending the EAPOL-Key - we will disconnect
3340 * immediately following this. */
3341 return;
3342 }
3343
3344 /* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, [MDIE],
Hai Shalomfdcde762020-04-02 11:19:20 -07003345 GTK[GN], IGTK, [BIGTK], [FTIE], [TIE * 2])
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003346 */
3347 os_memset(rsc, 0, WPA_KEY_RSC_LEN);
3348 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc);
3349 /* If FT is used, wpa_auth->wpa_ie includes both RSNIE and MDIE */
3350 wpa_ie = sm->wpa_auth->wpa_ie;
3351 wpa_ie_len = sm->wpa_auth->wpa_ie_len;
Hai Shalomfdcde762020-04-02 11:19:20 -07003352 if (sm->wpa == WPA_VERSION_WPA && (conf->wpa & WPA_PROTO_RSN) &&
3353 wpa_ie_len > wpa_ie[1] + 2U && wpa_ie[0] == WLAN_EID_RSN) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003354 /* WPA-only STA, remove RSN IE and possible MDIE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003355 wpa_ie = wpa_ie + wpa_ie[1] + 2;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003356 if (wpa_ie[0] == WLAN_EID_MOBILITY_DOMAIN)
3357 wpa_ie = wpa_ie + wpa_ie[1] + 2;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003358 wpa_ie_len = wpa_ie[1] + 2;
3359 }
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003360#ifdef CONFIG_TESTING_OPTIONS
Hai Shalomfdcde762020-04-02 11:19:20 -07003361 if (conf->rsne_override_eapol_set) {
3362 wpa_ie_buf2 = replace_ie(
3363 "RSNE", wpa_ie, &wpa_ie_len, WLAN_EID_RSN,
3364 conf->rsne_override_eapol,
3365 conf->rsne_override_eapol_len);
3366 if (!wpa_ie_buf2)
3367 goto done;
3368 wpa_ie = wpa_ie_buf2;
3369 }
3370 if (conf->rsnxe_override_eapol_set) {
3371 wpa_ie_buf = replace_ie(
3372 "RSNXE", wpa_ie, &wpa_ie_len, WLAN_EID_RSNX,
3373 conf->rsnxe_override_eapol,
3374 conf->rsnxe_override_eapol_len);
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003375 if (!wpa_ie_buf)
Hai Shalomfdcde762020-04-02 11:19:20 -07003376 goto done;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003377 wpa_ie = wpa_ie_buf;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003378 }
3379#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003380 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
3381 "sending 3/4 msg of 4-Way Handshake");
3382 if (sm->wpa == WPA_VERSION_WPA2) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003383 if (sm->use_ext_key_id && sm->TimeoutCtr == 1 &&
3384 wpa_auth_set_key(sm->wpa_auth, 0,
3385 wpa_cipher_to_alg(sm->pairwise),
3386 sm->addr,
3387 sm->keyidx_active, sm->PTK.tk,
3388 wpa_cipher_key_len(sm->pairwise),
3389 KEY_FLAG_PAIRWISE_RX)) {
3390 wpa_sta_disconnect(sm->wpa_auth, sm->addr,
3391 WLAN_REASON_PREV_AUTH_NOT_VALID);
3392 return;
3393 }
3394
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003395 /* WPA2 send GTK in the 4-way handshake */
3396 secure = 1;
3397 gtk = gsm->GTK[gsm->GN - 1];
3398 gtk_len = gsm->GTK_len;
Hai Shalomfdcde762020-04-02 11:19:20 -07003399 if (conf->disable_gtk ||
Roshan Pius3a1667e2018-07-03 15:17:14 -07003400 sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003401 /*
3402 * Provide unique random GTK to each STA to prevent use
3403 * of GTK in the BSS.
3404 */
3405 if (random_get_bytes(dummy_gtk, gtk_len) < 0)
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003406 goto done;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003407 gtk = dummy_gtk;
3408 }
Hai Shalomc3565922019-10-28 11:58:20 -07003409 gtkidx = gsm->GN;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003410 _rsc = rsc;
3411 encr = 1;
3412 } else {
3413 /* WPA does not include GTK in msg 3/4 */
3414 secure = 0;
3415 gtk = NULL;
3416 gtk_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003417 _rsc = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003418 if (sm->rx_eapol_key_secure) {
3419 /*
3420 * It looks like Windows 7 supplicant tries to use
3421 * Secure bit in msg 2/4 after having reported Michael
3422 * MIC failure and it then rejects the 4-way handshake
3423 * if msg 3/4 does not set Secure bit. Work around this
3424 * by setting the Secure bit here even in the case of
3425 * WPA if the supplicant used it first.
3426 */
3427 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07003428 "STA used Secure bit in WPA msg 2/4 - set Secure for 3/4 as workaround");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003429 secure = 1;
3430 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003431 }
3432
Hai Shalom74f70d42019-02-11 14:42:39 -08003433 kde_len = wpa_ie_len + ieee80211w_kde_len(sm) + ocv_oci_len(sm);
Hai Shalomfdcde762020-04-02 11:19:20 -07003434
3435 if (sm->use_ext_key_id)
3436 kde_len += 2 + RSN_SELECTOR_LEN + 2;
3437
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003438 if (gtk)
3439 kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003440#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003441 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
3442 kde_len += 2 + PMKID_LEN; /* PMKR1Name into RSN IE */
3443 kde_len += 300; /* FTIE + 2 * TIE */
3444 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003445#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08003446#ifdef CONFIG_P2P
3447 if (WPA_GET_BE32(sm->ip_addr) > 0)
3448 kde_len += 2 + RSN_SELECTOR_LEN + 3 * 4;
3449#endif /* CONFIG_P2P */
Hai Shalomfdcde762020-04-02 11:19:20 -07003450
3451 if (conf->transition_disable)
3452 kde_len += 2 + RSN_SELECTOR_LEN + 1;
3453
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003454#ifdef CONFIG_DPP2
3455 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP)
3456 kde_len += 2 + RSN_SELECTOR_LEN + 2;
3457#endif /* CONFIG_DPP2 */
3458
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003459 kde = os_malloc(kde_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07003460 if (!kde)
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003461 goto done;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003462
3463 pos = kde;
3464 os_memcpy(pos, wpa_ie, wpa_ie_len);
3465 pos += wpa_ie_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003466#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003467 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08003468 int res;
3469 size_t elen;
3470
3471 elen = pos - kde;
3472 res = wpa_insert_pmkid(kde, &elen, sm->pmk_r1_name);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003473 if (res < 0) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003474 wpa_printf(MSG_ERROR,
3475 "FT: Failed to insert PMKR1Name into RSN IE in EAPOL-Key data");
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003476 goto done;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003477 }
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08003478 pos -= wpa_ie_len;
3479 pos += elen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003480 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003481#endif /* CONFIG_IEEE80211R_AP */
Hai Shalomfdcde762020-04-02 11:19:20 -07003482 hdr[1] = 0;
3483
3484 if (sm->use_ext_key_id) {
3485 hdr[0] = sm->keyidx_active & 0x01;
3486 pos = wpa_add_kde(pos, RSN_KEY_DATA_KEYID, hdr, 2, NULL, 0);
3487 }
3488
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003489 if (gtk) {
Hai Shalomc3565922019-10-28 11:58:20 -07003490 hdr[0] = gtkidx & 0x03;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003491 pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
3492 gtk, gtk_len);
3493 }
3494 pos = ieee80211w_kde_add(sm, pos);
Hai Shalom899fcc72020-10-19 14:38:18 -07003495 if (ocv_oci_add(sm, &pos, conf->oci_freq_override_eapol_m3) < 0)
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003496 goto done;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003497
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003498#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003499 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
3500 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003501
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08003502 if (sm->assoc_resp_ftie &&
3503 kde + kde_len - pos >= 2 + sm->assoc_resp_ftie[1]) {
3504 os_memcpy(pos, sm->assoc_resp_ftie,
3505 2 + sm->assoc_resp_ftie[1]);
3506 res = 2 + sm->assoc_resp_ftie[1];
3507 } else {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003508 int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt);
3509
3510 res = wpa_write_ftie(conf, use_sha384,
3511 conf->r0_key_holder,
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08003512 conf->r0_key_holder_len,
3513 NULL, NULL, pos,
3514 kde + kde_len - pos,
Hai Shalomfdcde762020-04-02 11:19:20 -07003515 NULL, 0, 0);
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08003516 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003517 if (res < 0) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003518 wpa_printf(MSG_ERROR,
3519 "FT: Failed to insert FTIE into EAPOL-Key Key Data");
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003520 goto done;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003521 }
3522 pos += res;
3523
3524 /* TIE[ReassociationDeadline] (TU) */
3525 *pos++ = WLAN_EID_TIMEOUT_INTERVAL;
3526 *pos++ = 5;
3527 *pos++ = WLAN_TIMEOUT_REASSOC_DEADLINE;
3528 WPA_PUT_LE32(pos, conf->reassociation_deadline);
3529 pos += 4;
3530
3531 /* TIE[KeyLifetime] (seconds) */
3532 *pos++ = WLAN_EID_TIMEOUT_INTERVAL;
3533 *pos++ = 5;
3534 *pos++ = WLAN_TIMEOUT_KEY_LIFETIME;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003535 WPA_PUT_LE32(pos, conf->r0_key_lifetime);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003536 pos += 4;
3537 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003538#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08003539#ifdef CONFIG_P2P
3540 if (WPA_GET_BE32(sm->ip_addr) > 0) {
3541 u8 addr[3 * 4];
3542 os_memcpy(addr, sm->ip_addr, 4);
Hai Shalomfdcde762020-04-02 11:19:20 -07003543 os_memcpy(addr + 4, conf->ip_addr_mask, 4);
3544 os_memcpy(addr + 8, conf->ip_addr_go, 4);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08003545 pos = wpa_add_kde(pos, WFA_KEY_DATA_IP_ADDR_ALLOC,
3546 addr, sizeof(addr), NULL, 0);
3547 }
3548#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003549
Hai Shalomfdcde762020-04-02 11:19:20 -07003550 if (conf->transition_disable)
3551 pos = wpa_add_kde(pos, WFA_KEY_DATA_TRANSITION_DISABLE,
3552 &conf->transition_disable, 1, NULL, 0);
3553
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003554#ifdef CONFIG_DPP2
3555 if (DPP_VERSION > 1 && sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP) {
3556 u8 payload[2];
3557
3558 payload[0] = DPP_VERSION; /* Protocol Version */
3559 payload[1] = 0; /* Flags */
3560 if (conf->dpp_pfs == 0)
3561 payload[1] |= DPP_KDE_PFS_ALLOWED;
3562 else if (conf->dpp_pfs == 1)
3563 payload[1] |= DPP_KDE_PFS_ALLOWED |
3564 DPP_KDE_PFS_REQUIRED;
3565 pos = wpa_add_kde(pos, WFA_KEY_DATA_DPP,
3566 payload, sizeof(payload), NULL, 0);
3567 }
3568#endif /* CONFIG_DPP2 */
3569
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003570 wpa_send_eapol(sm->wpa_auth, sm,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003571 (secure ? WPA_KEY_INFO_SECURE : 0) |
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003572 (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
3573 WPA_KEY_INFO_MIC : 0) |
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003574 WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL |
3575 WPA_KEY_INFO_KEY_TYPE,
Hai Shalomc3565922019-10-28 11:58:20 -07003576 _rsc, sm->ANonce, kde, pos - kde, 0, encr);
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003577done:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003578 os_free(kde);
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003579 os_free(wpa_ie_buf);
Hai Shalomfdcde762020-04-02 11:19:20 -07003580 os_free(wpa_ie_buf2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003581}
3582
3583
3584SM_STATE(WPA_PTK, PTKINITDONE)
3585{
3586 SM_ENTRY_MA(WPA_PTK, PTKINITDONE, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07003587 sm->EAPOLKeyReceived = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003588 if (sm->Pair) {
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07003589 enum wpa_alg alg = wpa_cipher_to_alg(sm->pairwise);
3590 int klen = wpa_cipher_key_len(sm->pairwise);
Hai Shalomfdcde762020-04-02 11:19:20 -07003591 int res;
3592
3593 if (sm->use_ext_key_id)
3594 res = wpa_auth_set_key(sm->wpa_auth, 0, 0, sm->addr,
3595 sm->keyidx_active, NULL, 0,
3596 KEY_FLAG_PAIRWISE_RX_TX_MODIFY);
3597 else
3598 res = wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr,
3599 0, sm->PTK.tk, klen,
3600 KEY_FLAG_PAIRWISE_RX_TX);
3601 if (res) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003602 wpa_sta_disconnect(sm->wpa_auth, sm->addr,
3603 WLAN_REASON_PREV_AUTH_NOT_VALID);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003604 return;
3605 }
3606 /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */
Hai Shalome21d4e82020-04-29 16:34:06 -07003607 sm->pairwise_set = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003608
Hai Shalom81f62d82019-07-22 12:10:00 -07003609 wpa_auth_set_ptk_rekey_timer(sm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003610
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003611 if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
3612 sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP ||
3613 sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003614 wpa_auth_set_eapol(sm->wpa_auth, sm->addr,
3615 WPA_EAPOL_authorized, 1);
3616 }
3617 }
3618
3619 if (0 /* IBSS == TRUE */) {
3620 sm->keycount++;
3621 if (sm->keycount == 2) {
3622 wpa_auth_set_eapol(sm->wpa_auth, sm->addr,
3623 WPA_EAPOL_portValid, 1);
3624 }
3625 } else {
3626 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid,
3627 1);
3628 }
Hai Shalome21d4e82020-04-29 16:34:06 -07003629 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyAvailable,
3630 false);
3631 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyDone, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003632 if (sm->wpa == WPA_VERSION_WPA)
Hai Shalome21d4e82020-04-29 16:34:06 -07003633 sm->PInitAKeys = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003634 else
Hai Shalome21d4e82020-04-29 16:34:06 -07003635 sm->has_GTK = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003636 wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO,
3637 "pairwise key handshake completed (%s)",
3638 sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN");
3639
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003640#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003641 wpa_ft_push_pmk_r1(sm->wpa_auth, sm->addr);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003642#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003643}
3644
3645
3646SM_STEP(WPA_PTK)
3647{
3648 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
Hai Shalomfdcde762020-04-02 11:19:20 -07003649 struct wpa_auth_config *conf = &wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003650
3651 if (sm->Init)
3652 SM_ENTER(WPA_PTK, INITIALIZE);
3653 else if (sm->Disconnect
3654 /* || FIX: dot11RSNAConfigSALifetime timeout */) {
3655 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
3656 "WPA_PTK: sm->Disconnect");
3657 SM_ENTER(WPA_PTK, DISCONNECT);
3658 }
3659 else if (sm->DeauthenticationRequest)
3660 SM_ENTER(WPA_PTK, DISCONNECTED);
3661 else if (sm->AuthenticationRequest)
3662 SM_ENTER(WPA_PTK, AUTHENTICATION);
3663 else if (sm->ReAuthenticationRequest)
3664 SM_ENTER(WPA_PTK, AUTHENTICATION2);
Jouni Malinen1420a892017-10-01 12:32:57 +03003665 else if (sm->PTKRequest) {
3666 if (wpa_auth_sm_ptk_update(sm) < 0)
3667 SM_ENTER(WPA_PTK, DISCONNECTED);
3668 else
3669 SM_ENTER(WPA_PTK, PTKSTART);
3670 } else switch (sm->wpa_ptk_state) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003671 case WPA_PTK_INITIALIZE:
3672 break;
3673 case WPA_PTK_DISCONNECT:
3674 SM_ENTER(WPA_PTK, DISCONNECTED);
3675 break;
3676 case WPA_PTK_DISCONNECTED:
3677 SM_ENTER(WPA_PTK, INITIALIZE);
3678 break;
3679 case WPA_PTK_AUTHENTICATION:
3680 SM_ENTER(WPA_PTK, AUTHENTICATION2);
3681 break;
3682 case WPA_PTK_AUTHENTICATION2:
3683 if (wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) &&
Hai Shalomfdcde762020-04-02 11:19:20 -07003684 wpa_auth_get_eapol(wpa_auth, sm->addr,
Hai Shalome21d4e82020-04-29 16:34:06 -07003685 WPA_EAPOL_keyRun))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003686 SM_ENTER(WPA_PTK, INITPMK);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003687 else if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
3688 sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003689 /* FIX: && 802.1X::keyRun */)
3690 SM_ENTER(WPA_PTK, INITPSK);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003691 else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP)
3692 SM_ENTER(WPA_PTK, INITPMK);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003693 break;
3694 case WPA_PTK_INITPMK:
Hai Shalomfdcde762020-04-02 11:19:20 -07003695 if (wpa_auth_get_eapol(wpa_auth, sm->addr,
Hai Shalome21d4e82020-04-29 16:34:06 -07003696 WPA_EAPOL_keyAvailable)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003697 SM_ENTER(WPA_PTK, PTKSTART);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003698#ifdef CONFIG_DPP
3699 } else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP && sm->pmksa) {
3700 SM_ENTER(WPA_PTK, PTKSTART);
3701#endif /* CONFIG_DPP */
3702 } else {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003703 wpa_auth->dot11RSNA4WayHandshakeFailures++;
Hai Shalomfdcde762020-04-02 11:19:20 -07003704 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003705 "INITPMK - keyAvailable = false");
3706 SM_ENTER(WPA_PTK, DISCONNECT);
3707 }
3708 break;
3709 case WPA_PTK_INITPSK:
Hai Shalomfdcde762020-04-02 11:19:20 -07003710 if (wpa_auth_get_psk(wpa_auth, sm->addr, sm->p2p_dev_addr,
Hai Shalom021b0b52019-04-10 11:17:58 -07003711 NULL, NULL, NULL)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003712 SM_ENTER(WPA_PTK, PTKSTART);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003713#ifdef CONFIG_SAE
3714 } else if (wpa_auth_uses_sae(sm) && sm->pmksa) {
3715 SM_ENTER(WPA_PTK, PTKSTART);
3716#endif /* CONFIG_SAE */
3717 } else {
Hai Shalomfdcde762020-04-02 11:19:20 -07003718 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003719 "no PSK configured for the STA");
3720 wpa_auth->dot11RSNA4WayHandshakeFailures++;
3721 SM_ENTER(WPA_PTK, DISCONNECT);
3722 }
3723 break;
3724 case WPA_PTK_PTKSTART:
3725 if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest &&
3726 sm->EAPOLKeyPairwise)
3727 SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING);
Hai Shalomfdcde762020-04-02 11:19:20 -07003728 else if (sm->TimeoutCtr > conf->wpa_pairwise_update_count) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003729 wpa_auth->dot11RSNA4WayHandshakeFailures++;
Hai Shalomfdcde762020-04-02 11:19:20 -07003730 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
3731 "PTKSTART: Retry limit %u reached",
3732 conf->wpa_pairwise_update_count);
Hai Shalome21d4e82020-04-29 16:34:06 -07003733 sm->disconnect_reason =
3734 WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003735 SM_ENTER(WPA_PTK, DISCONNECT);
3736 } else if (sm->TimeoutEvt)
3737 SM_ENTER(WPA_PTK, PTKSTART);
3738 break;
3739 case WPA_PTK_PTKCALCNEGOTIATING:
3740 if (sm->MICVerified)
3741 SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING2);
3742 else if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest &&
3743 sm->EAPOLKeyPairwise)
3744 SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING);
3745 else if (sm->TimeoutEvt)
3746 SM_ENTER(WPA_PTK, PTKSTART);
3747 break;
3748 case WPA_PTK_PTKCALCNEGOTIATING2:
3749 SM_ENTER(WPA_PTK, PTKINITNEGOTIATING);
3750 break;
3751 case WPA_PTK_PTKINITNEGOTIATING:
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003752 if (sm->update_snonce)
3753 SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING);
3754 else if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest &&
3755 sm->EAPOLKeyPairwise && sm->MICVerified)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003756 SM_ENTER(WPA_PTK, PTKINITDONE);
3757 else if (sm->TimeoutCtr >
Hai Shalomfdcde762020-04-02 11:19:20 -07003758 conf->wpa_pairwise_update_count ||
3759 (conf->wpa_disable_eapol_key_retries &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003760 sm->TimeoutCtr > 1)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003761 wpa_auth->dot11RSNA4WayHandshakeFailures++;
Hai Shalomfdcde762020-04-02 11:19:20 -07003762 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
3763 "PTKINITNEGOTIATING: Retry limit %u reached",
3764 conf->wpa_pairwise_update_count);
Hai Shalome21d4e82020-04-29 16:34:06 -07003765 sm->disconnect_reason =
3766 WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003767 SM_ENTER(WPA_PTK, DISCONNECT);
3768 } else if (sm->TimeoutEvt)
3769 SM_ENTER(WPA_PTK, PTKINITNEGOTIATING);
3770 break;
3771 case WPA_PTK_PTKINITDONE:
3772 break;
3773 }
3774}
3775
3776
3777SM_STATE(WPA_PTK_GROUP, IDLE)
3778{
3779 SM_ENTRY_MA(WPA_PTK_GROUP, IDLE, wpa_ptk_group);
3780 if (sm->Init) {
3781 /* Init flag is not cleared here, so avoid busy
3782 * loop by claiming nothing changed. */
Hai Shalome21d4e82020-04-29 16:34:06 -07003783 sm->changed = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003784 }
3785 sm->GTimeoutCtr = 0;
3786}
3787
3788
3789SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING)
3790{
3791 u8 rsc[WPA_KEY_RSC_LEN];
3792 struct wpa_group *gsm = sm->group;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003793 const u8 *kde;
3794 u8 *kde_buf = NULL, *pos, hdr[2];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003795 size_t kde_len;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003796 u8 *gtk, dummy_gtk[32];
Hai Shalomfdcde762020-04-02 11:19:20 -07003797 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003798
3799 SM_ENTRY_MA(WPA_PTK_GROUP, REKEYNEGOTIATING, wpa_ptk_group);
3800
3801 sm->GTimeoutCtr++;
Hai Shalomfdcde762020-04-02 11:19:20 -07003802 if (conf->wpa_disable_eapol_key_retries && sm->GTimeoutCtr > 1) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003803 /* Do not allow retransmission of EAPOL-Key group msg 1/2 */
3804 return;
3805 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003806 if (sm->GTimeoutCtr > conf->wpa_group_update_count) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003807 /* No point in sending the EAPOL-Key - we will disconnect
3808 * immediately following this. */
3809 return;
3810 }
3811
3812 if (sm->wpa == WPA_VERSION_WPA)
Hai Shalome21d4e82020-04-29 16:34:06 -07003813 sm->PInitAKeys = false;
3814 sm->TimeoutEvt = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003815 /* Send EAPOL(1, 1, 1, !Pair, G, RSC, GNonce, MIC(PTK), GTK[GN]) */
3816 os_memset(rsc, 0, WPA_KEY_RSC_LEN);
3817 if (gsm->wpa_group_state == WPA_GROUP_SETKEYSDONE)
3818 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc);
3819 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
3820 "sending 1/2 msg of Group Key Handshake");
3821
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003822 gtk = gsm->GTK[gsm->GN - 1];
Hai Shalomfdcde762020-04-02 11:19:20 -07003823 if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003824 /*
3825 * Provide unique random GTK to each STA to prevent use
3826 * of GTK in the BSS.
3827 */
3828 if (random_get_bytes(dummy_gtk, gsm->GTK_len) < 0)
3829 return;
3830 gtk = dummy_gtk;
3831 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003832 if (sm->wpa == WPA_VERSION_WPA2) {
3833 kde_len = 2 + RSN_SELECTOR_LEN + 2 + gsm->GTK_len +
Hai Shalom74f70d42019-02-11 14:42:39 -08003834 ieee80211w_kde_len(sm) + ocv_oci_len(sm);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003835 kde_buf = os_malloc(kde_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07003836 if (!kde_buf)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003837 return;
3838
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003839 kde = pos = kde_buf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003840 hdr[0] = gsm->GN & 0x03;
3841 hdr[1] = 0;
3842 pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003843 gtk, gsm->GTK_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003844 pos = ieee80211w_kde_add(sm, pos);
Hai Shalom899fcc72020-10-19 14:38:18 -07003845 if (ocv_oci_add(sm, &pos,
3846 conf->oci_freq_override_eapol_g1) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -08003847 os_free(kde_buf);
3848 return;
3849 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003850 kde_len = pos - kde;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003851 } else {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003852 kde = gtk;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003853 kde_len = gsm->GTK_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003854 }
3855
3856 wpa_send_eapol(sm->wpa_auth, sm,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003857 WPA_KEY_INFO_SECURE |
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003858 (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
3859 WPA_KEY_INFO_MIC : 0) |
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003860 WPA_KEY_INFO_ACK |
3861 (!sm->Pair ? WPA_KEY_INFO_INSTALL : 0),
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003862 rsc, NULL, kde, kde_len, gsm->GN, 1);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003863
3864 os_free(kde_buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003865}
3866
3867
3868SM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED)
3869{
Hai Shalom74f70d42019-02-11 14:42:39 -08003870 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
Hai Shalomfdcde762020-04-02 11:19:20 -07003871#ifdef CONFIG_OCV
Hai Shalom74f70d42019-02-11 14:42:39 -08003872 const u8 *key_data, *mic;
3873 struct ieee802_1x_hdr *hdr;
3874 struct wpa_eapol_key *key;
3875 struct wpa_eapol_ie_parse kde;
3876 size_t mic_len;
3877 u16 key_data_length;
3878#endif /* CONFIG_OCV */
3879
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003880 SM_ENTRY_MA(WPA_PTK_GROUP, REKEYESTABLISHED, wpa_ptk_group);
Hai Shalome21d4e82020-04-29 16:34:06 -07003881 sm->EAPOLKeyReceived = false;
Hai Shalom74f70d42019-02-11 14:42:39 -08003882
3883#ifdef CONFIG_OCV
3884 mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
3885
3886 /*
3887 * Note: last_rx_eapol_key length fields have already been validated in
3888 * wpa_receive().
3889 */
3890 hdr = (struct ieee802_1x_hdr *) sm->last_rx_eapol_key;
3891 key = (struct wpa_eapol_key *) (hdr + 1);
3892 mic = (u8 *) (key + 1);
3893 key_data = mic + mic_len + 2;
3894 key_data_length = WPA_GET_BE16(mic + mic_len);
3895 if (key_data_length > sm->last_rx_eapol_key_len - sizeof(*hdr) -
3896 sizeof(*key) - mic_len - 2)
3897 return;
3898
3899 if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) {
3900 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
3901 "received EAPOL-Key group msg 2/2 with invalid Key Data contents");
3902 return;
3903 }
3904
3905 if (wpa_auth_uses_ocv(sm)) {
3906 struct wpa_channel_info ci;
3907 int tx_chanwidth;
3908 int tx_seg1_idx;
3909
3910 if (wpa_channel_info(wpa_auth, &ci) != 0) {
3911 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalom899fcc72020-10-19 14:38:18 -07003912 "Failed to get channel info to validate received OCI in EAPOL-Key group 2/2");
Hai Shalom74f70d42019-02-11 14:42:39 -08003913 return;
3914 }
3915
3916 if (get_sta_tx_parameters(sm,
3917 channel_width_to_int(ci.chanwidth),
3918 ci.seg1_idx, &tx_chanwidth,
3919 &tx_seg1_idx) < 0)
3920 return;
3921
3922 if (ocv_verify_tx_params(kde.oci, kde.oci_len, &ci,
Hai Shalom899fcc72020-10-19 14:38:18 -07003923 tx_chanwidth, tx_seg1_idx) !=
3924 OCI_SUCCESS) {
3925 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
3926 "OCV failed: %s", ocv_errorstr);
3927 if (wpa_auth->conf.msg_ctx)
3928 wpa_msg(wpa_auth->conf.msg_ctx, MSG_INFO,
3929 OCV_FAILURE "addr=" MACSTR
3930 " frame=eapol-key-g2 error=%s",
3931 MAC2STR(sm->addr), ocv_errorstr);
Hai Shalom74f70d42019-02-11 14:42:39 -08003932 return;
3933 }
3934 }
3935#endif /* CONFIG_OCV */
3936
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003937 if (sm->GUpdateStationKeys)
3938 sm->group->GKeyDoneStations--;
Hai Shalome21d4e82020-04-29 16:34:06 -07003939 sm->GUpdateStationKeys = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003940 sm->GTimeoutCtr = 0;
3941 /* FIX: MLME.SetProtection.Request(TA, Tx_Rx) */
Hai Shalomfdcde762020-04-02 11:19:20 -07003942 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003943 "group key handshake completed (%s)",
3944 sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN");
Hai Shalome21d4e82020-04-29 16:34:06 -07003945 sm->has_GTK = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003946}
3947
3948
3949SM_STATE(WPA_PTK_GROUP, KEYERROR)
3950{
3951 SM_ENTRY_MA(WPA_PTK_GROUP, KEYERROR, wpa_ptk_group);
3952 if (sm->GUpdateStationKeys)
3953 sm->group->GKeyDoneStations--;
Hai Shalome21d4e82020-04-29 16:34:06 -07003954 sm->GUpdateStationKeys = false;
3955 sm->Disconnect = true;
3956 sm->disconnect_reason = WLAN_REASON_GROUP_KEY_UPDATE_TIMEOUT;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003957 wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO,
3958 "group key handshake failed (%s) after %u tries",
3959 sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN",
3960 sm->wpa_auth->conf.wpa_group_update_count);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003961}
3962
3963
3964SM_STEP(WPA_PTK_GROUP)
3965{
3966 if (sm->Init || sm->PtkGroupInit) {
3967 SM_ENTER(WPA_PTK_GROUP, IDLE);
Hai Shalome21d4e82020-04-29 16:34:06 -07003968 sm->PtkGroupInit = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003969 } else switch (sm->wpa_ptk_group_state) {
3970 case WPA_PTK_GROUP_IDLE:
3971 if (sm->GUpdateStationKeys ||
3972 (sm->wpa == WPA_VERSION_WPA && sm->PInitAKeys))
3973 SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING);
3974 break;
3975 case WPA_PTK_GROUP_REKEYNEGOTIATING:
3976 if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest &&
3977 !sm->EAPOLKeyPairwise && sm->MICVerified)
3978 SM_ENTER(WPA_PTK_GROUP, REKEYESTABLISHED);
3979 else if (sm->GTimeoutCtr >
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003980 sm->wpa_auth->conf.wpa_group_update_count ||
3981 (sm->wpa_auth->conf.wpa_disable_eapol_key_retries &&
3982 sm->GTimeoutCtr > 1))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003983 SM_ENTER(WPA_PTK_GROUP, KEYERROR);
3984 else if (sm->TimeoutEvt)
3985 SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING);
3986 break;
3987 case WPA_PTK_GROUP_KEYERROR:
3988 SM_ENTER(WPA_PTK_GROUP, IDLE);
3989 break;
3990 case WPA_PTK_GROUP_REKEYESTABLISHED:
3991 SM_ENTER(WPA_PTK_GROUP, IDLE);
3992 break;
3993 }
3994}
3995
3996
3997static int wpa_gtk_update(struct wpa_authenticator *wpa_auth,
3998 struct wpa_group *group)
3999{
Hai Shalomfdcde762020-04-02 11:19:20 -07004000 struct wpa_auth_config *conf = &wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004001 int ret = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07004002 size_t len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004003
4004 os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
4005 inc_byte_array(group->Counter, WPA_NONCE_LEN);
4006 if (wpa_gmk_to_gtk(group->GMK, "Group key expansion",
4007 wpa_auth->addr, group->GNonce,
4008 group->GTK[group->GN - 1], group->GTK_len) < 0)
4009 ret = -1;
4010 wpa_hexdump_key(MSG_DEBUG, "GTK",
4011 group->GTK[group->GN - 1], group->GTK_len);
4012
Hai Shalomfdcde762020-04-02 11:19:20 -07004013 if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
4014 len = wpa_cipher_key_len(conf->group_mgmt_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004015 os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
4016 inc_byte_array(group->Counter, WPA_NONCE_LEN);
4017 if (wpa_gmk_to_gtk(group->GMK, "IGTK key expansion",
4018 wpa_auth->addr, group->GNonce,
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004019 group->IGTK[group->GN_igtk - 4], len) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004020 ret = -1;
4021 wpa_hexdump_key(MSG_DEBUG, "IGTK",
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004022 group->IGTK[group->GN_igtk - 4], len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004023 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004024
Hai Shalomfdcde762020-04-02 11:19:20 -07004025 if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION &&
4026 conf->beacon_prot) {
4027 len = wpa_cipher_key_len(conf->group_mgmt_cipher);
4028 os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
4029 inc_byte_array(group->Counter, WPA_NONCE_LEN);
4030 if (wpa_gmk_to_gtk(group->GMK, "BIGTK key expansion",
4031 wpa_auth->addr, group->GNonce,
4032 group->BIGTK[group->GN_bigtk - 6], len) < 0)
4033 ret = -1;
4034 wpa_hexdump_key(MSG_DEBUG, "BIGTK",
4035 group->BIGTK[group->GN_bigtk - 6], len);
4036 }
4037
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004038 return ret;
4039}
4040
4041
4042static void wpa_group_gtk_init(struct wpa_authenticator *wpa_auth,
4043 struct wpa_group *group)
4044{
Hai Shalomfdcde762020-04-02 11:19:20 -07004045 wpa_printf(MSG_DEBUG,
4046 "WPA: group state machine entering state GTK_INIT (VLAN-ID %d)",
4047 group->vlan_id);
Hai Shalome21d4e82020-04-29 16:34:06 -07004048 group->changed = false; /* GInit is not cleared here; avoid loop */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004049 group->wpa_group_state = WPA_GROUP_GTK_INIT;
4050
4051 /* GTK[0..N] = 0 */
4052 os_memset(group->GTK, 0, sizeof(group->GTK));
4053 group->GN = 1;
4054 group->GM = 2;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004055 group->GN_igtk = 4;
4056 group->GM_igtk = 5;
Hai Shalomfdcde762020-04-02 11:19:20 -07004057 group->GN_bigtk = 6;
4058 group->GM_bigtk = 7;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004059 /* GTK[GN] = CalcGTK() */
4060 wpa_gtk_update(wpa_auth, group);
4061}
4062
4063
4064static int wpa_group_update_sta(struct wpa_state_machine *sm, void *ctx)
4065{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004066 if (ctx != NULL && ctx != sm->group)
4067 return 0;
4068
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004069 if (sm->wpa_ptk_state != WPA_PTK_PTKINITDONE) {
4070 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
4071 "Not in PTKINITDONE; skip Group Key update");
Hai Shalome21d4e82020-04-29 16:34:06 -07004072 sm->GUpdateStationKeys = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004073 return 0;
4074 }
4075 if (sm->GUpdateStationKeys) {
4076 /*
4077 * This should not really happen, so add a debug log entry.
4078 * Since we clear the GKeyDoneStations before the loop, the
4079 * station needs to be counted here anyway.
4080 */
4081 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07004082 "GUpdateStationKeys was already set when marking station for GTK rekeying");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004083 }
4084
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004085 /* Do not rekey GTK/IGTK when STA is in WNM-Sleep Mode */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004086 if (sm->is_wnmsleep)
4087 return 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004088
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004089 sm->group->GKeyDoneStations++;
Hai Shalome21d4e82020-04-29 16:34:06 -07004090 sm->GUpdateStationKeys = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004091
4092 wpa_sm_step(sm);
4093 return 0;
4094}
4095
4096
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004097#ifdef CONFIG_WNM_AP
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004098/* update GTK when exiting WNM-Sleep Mode */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004099void wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm)
4100{
Hai Shalomfdcde762020-04-02 11:19:20 -07004101 if (!sm || sm->is_wnmsleep)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004102 return;
4103
4104 wpa_group_update_sta(sm, NULL);
4105}
4106
4107
4108void wpa_set_wnmsleep(struct wpa_state_machine *sm, int flag)
4109{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004110 if (sm)
4111 sm->is_wnmsleep = !!flag;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004112}
4113
4114
4115int wpa_wnmsleep_gtk_subelem(struct wpa_state_machine *sm, u8 *pos)
4116{
Hai Shalom899fcc72020-10-19 14:38:18 -07004117 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004118 struct wpa_group *gsm = sm->group;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004119 u8 *start = pos;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004120
4121 /*
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004122 * GTK subelement:
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004123 * Sub-elem ID[1] | Length[1] | Key Info[2] | Key Length[1] | RSC[8] |
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004124 * Key[5..32]
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004125 */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004126 *pos++ = WNM_SLEEP_SUBELEM_GTK;
4127 *pos++ = 11 + gsm->GTK_len;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004128 /* Key ID in B0-B1 of Key Info */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004129 WPA_PUT_LE16(pos, gsm->GN & 0x03);
4130 pos += 2;
4131 *pos++ = gsm->GTK_len;
4132 if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, pos) != 0)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004133 return 0;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004134 pos += 8;
4135 os_memcpy(pos, gsm->GTK[gsm->GN - 1], gsm->GTK_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07004136 if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
4137 /*
4138 * Provide unique random GTK to each STA to prevent use
4139 * of GTK in the BSS.
4140 */
4141 if (random_get_bytes(pos, gsm->GTK_len) < 0)
4142 return 0;
4143 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004144 pos += gsm->GTK_len;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004145
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004146 wpa_printf(MSG_DEBUG, "WNM: GTK Key ID %u in WNM-Sleep Mode exit",
4147 gsm->GN);
4148 wpa_hexdump_key(MSG_DEBUG, "WNM: GTK in WNM-Sleep Mode exit",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004149 gsm->GTK[gsm->GN - 1], gsm->GTK_len);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004150
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004151 return pos - start;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004152}
4153
4154
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004155int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos)
4156{
Hai Shalom899fcc72020-10-19 14:38:18 -07004157 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004158 struct wpa_group *gsm = sm->group;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004159 u8 *start = pos;
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004160 size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004161
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004162 /*
4163 * IGTK subelement:
4164 * Sub-elem ID[1] | Length[1] | KeyID[2] | PN[6] | Key[16]
4165 */
4166 *pos++ = WNM_SLEEP_SUBELEM_IGTK;
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004167 *pos++ = 2 + 6 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004168 WPA_PUT_LE16(pos, gsm->GN_igtk);
4169 pos += 2;
4170 if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, pos) != 0)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004171 return 0;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004172 pos += 6;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004173
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004174 os_memcpy(pos, gsm->IGTK[gsm->GN_igtk - 4], len);
Hai Shalom899fcc72020-10-19 14:38:18 -07004175 if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
4176 /*
4177 * Provide unique random IGTK to each STA to prevent use
4178 * of IGTK in the BSS.
4179 */
4180 if (random_get_bytes(pos, len) < 0)
4181 return 0;
4182 }
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004183 pos += len;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004184
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004185 wpa_printf(MSG_DEBUG, "WNM: IGTK Key ID %u in WNM-Sleep Mode exit",
4186 gsm->GN_igtk);
4187 wpa_hexdump_key(MSG_DEBUG, "WNM: IGTK in WNM-Sleep Mode exit",
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004188 gsm->IGTK[gsm->GN_igtk - 4], len);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004189
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004190 return pos - start;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004191}
Hai Shalomc3565922019-10-28 11:58:20 -07004192
Hai Shalomfdcde762020-04-02 11:19:20 -07004193
4194int wpa_wnmsleep_bigtk_subelem(struct wpa_state_machine *sm, u8 *pos)
4195{
4196 struct wpa_group *gsm = sm->group;
4197 u8 *start = pos;
4198 size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
4199
4200 /*
4201 * BIGTK subelement:
4202 * Sub-elem ID[1] | Length[1] | KeyID[2] | PN[6] | Key[16]
4203 */
4204 *pos++ = WNM_SLEEP_SUBELEM_BIGTK;
4205 *pos++ = 2 + 6 + len;
4206 WPA_PUT_LE16(pos, gsm->GN_bigtk);
4207 pos += 2;
4208 if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_bigtk, pos) != 0)
4209 return 0;
4210 pos += 6;
4211
4212 os_memcpy(pos, gsm->BIGTK[gsm->GN_bigtk - 6], len);
Hai Shalom899fcc72020-10-19 14:38:18 -07004213 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
4214 /*
4215 * Provide unique random BIGTK to each STA to prevent use
4216 * of BIGTK in the BSS.
4217 */
4218 if (random_get_bytes(pos, len) < 0)
4219 return 0;
4220 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004221 pos += len;
4222
4223 wpa_printf(MSG_DEBUG, "WNM: BIGTK Key ID %u in WNM-Sleep Mode exit",
4224 gsm->GN_bigtk);
4225 wpa_hexdump_key(MSG_DEBUG, "WNM: BIGTK in WNM-Sleep Mode exit",
4226 gsm->IGTK[gsm->GN_bigtk - 6], len);
4227
4228 return pos - start;
4229}
4230
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004231#endif /* CONFIG_WNM_AP */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004232
4233
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004234static void wpa_group_setkeys(struct wpa_authenticator *wpa_auth,
4235 struct wpa_group *group)
4236{
4237 int tmp;
4238
Hai Shalomfdcde762020-04-02 11:19:20 -07004239 wpa_printf(MSG_DEBUG,
4240 "WPA: group state machine entering state SETKEYS (VLAN-ID %d)",
4241 group->vlan_id);
Hai Shalome21d4e82020-04-29 16:34:06 -07004242 group->changed = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004243 group->wpa_group_state = WPA_GROUP_SETKEYS;
Hai Shalome21d4e82020-04-29 16:34:06 -07004244 group->GTKReKey = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004245 tmp = group->GM;
4246 group->GM = group->GN;
4247 group->GN = tmp;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004248 tmp = group->GM_igtk;
4249 group->GM_igtk = group->GN_igtk;
4250 group->GN_igtk = tmp;
Hai Shalomfdcde762020-04-02 11:19:20 -07004251 tmp = group->GM_bigtk;
4252 group->GM_bigtk = group->GN_bigtk;
4253 group->GN_bigtk = tmp;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004254 /* "GKeyDoneStations = GNoStations" is done in more robust way by
4255 * counting the STAs that are marked with GUpdateStationKeys instead of
4256 * including all STAs that could be in not-yet-completed state. */
4257 wpa_gtk_update(wpa_auth, group);
4258
4259 if (group->GKeyDoneStations) {
Hai Shalomfdcde762020-04-02 11:19:20 -07004260 wpa_printf(MSG_DEBUG,
4261 "wpa_group_setkeys: Unexpected GKeyDoneStations=%d when starting new GTK rekey",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004262 group->GKeyDoneStations);
4263 group->GKeyDoneStations = 0;
4264 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004265 wpa_auth_for_each_sta(wpa_auth, wpa_group_update_sta, group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004266 wpa_printf(MSG_DEBUG, "wpa_group_setkeys: GKeyDoneStations=%d",
4267 group->GKeyDoneStations);
4268}
4269
4270
4271static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth,
4272 struct wpa_group *group)
4273{
Hai Shalomfdcde762020-04-02 11:19:20 -07004274 struct wpa_auth_config *conf = &wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004275 int ret = 0;
4276
4277 if (wpa_auth_set_key(wpa_auth, group->vlan_id,
Hai Shalomfdcde762020-04-02 11:19:20 -07004278 wpa_cipher_to_alg(conf->wpa_group),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004279 broadcast_ether_addr, group->GN,
Hai Shalomfdcde762020-04-02 11:19:20 -07004280 group->GTK[group->GN - 1], group->GTK_len,
4281 KEY_FLAG_GROUP_TX_DEFAULT) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004282 ret = -1;
4283
Hai Shalomfdcde762020-04-02 11:19:20 -07004284 if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004285 enum wpa_alg alg;
4286 size_t len;
4287
Hai Shalomfdcde762020-04-02 11:19:20 -07004288 alg = wpa_cipher_to_alg(conf->group_mgmt_cipher);
4289 len = wpa_cipher_key_len(conf->group_mgmt_cipher);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004290
4291 if (ret == 0 &&
4292 wpa_auth_set_key(wpa_auth, group->vlan_id, alg,
4293 broadcast_ether_addr, group->GN_igtk,
Hai Shalomfdcde762020-04-02 11:19:20 -07004294 group->IGTK[group->GN_igtk - 4], len,
4295 KEY_FLAG_GROUP_TX_DEFAULT) < 0)
4296 ret = -1;
4297
4298 if (ret == 0 && conf->beacon_prot &&
4299 wpa_auth_set_key(wpa_auth, group->vlan_id, alg,
4300 broadcast_ether_addr, group->GN_bigtk,
4301 group->BIGTK[group->GN_bigtk - 6], len,
4302 KEY_FLAG_GROUP_TX_DEFAULT) < 0)
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004303 ret = -1;
4304 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004305
4306 return ret;
4307}
4308
4309
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004310static int wpa_group_disconnect_cb(struct wpa_state_machine *sm, void *ctx)
4311{
4312 if (sm->group == ctx) {
4313 wpa_printf(MSG_DEBUG, "WPA: Mark STA " MACSTR
Hai Shalomfdcde762020-04-02 11:19:20 -07004314 " for disconnection due to fatal failure",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004315 MAC2STR(sm->addr));
Hai Shalome21d4e82020-04-29 16:34:06 -07004316 sm->Disconnect = true;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004317 }
4318
4319 return 0;
4320}
4321
4322
4323static void wpa_group_fatal_failure(struct wpa_authenticator *wpa_auth,
4324 struct wpa_group *group)
4325{
Hai Shalomfdcde762020-04-02 11:19:20 -07004326 wpa_printf(MSG_DEBUG,
4327 "WPA: group state machine entering state FATAL_FAILURE");
Hai Shalome21d4e82020-04-29 16:34:06 -07004328 group->changed = true;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004329 group->wpa_group_state = WPA_GROUP_FATAL_FAILURE;
4330 wpa_auth_for_each_sta(wpa_auth, wpa_group_disconnect_cb, group);
4331}
4332
4333
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004334static int wpa_group_setkeysdone(struct wpa_authenticator *wpa_auth,
4335 struct wpa_group *group)
4336{
Hai Shalomfdcde762020-04-02 11:19:20 -07004337 wpa_printf(MSG_DEBUG,
4338 "WPA: group state machine entering state SETKEYSDONE (VLAN-ID %d)",
4339 group->vlan_id);
Hai Shalome21d4e82020-04-29 16:34:06 -07004340 group->changed = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004341 group->wpa_group_state = WPA_GROUP_SETKEYSDONE;
4342
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004343 if (wpa_group_config_group_keys(wpa_auth, group) < 0) {
4344 wpa_group_fatal_failure(wpa_auth, group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004345 return -1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004346 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004347
4348 return 0;
4349}
4350
4351
4352static void wpa_group_sm_step(struct wpa_authenticator *wpa_auth,
4353 struct wpa_group *group)
4354{
4355 if (group->GInit) {
4356 wpa_group_gtk_init(wpa_auth, group);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004357 } else if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) {
4358 /* Do not allow group operations */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004359 } else if (group->wpa_group_state == WPA_GROUP_GTK_INIT &&
4360 group->GTKAuthenticator) {
4361 wpa_group_setkeysdone(wpa_auth, group);
4362 } else if (group->wpa_group_state == WPA_GROUP_SETKEYSDONE &&
4363 group->GTKReKey) {
4364 wpa_group_setkeys(wpa_auth, group);
4365 } else if (group->wpa_group_state == WPA_GROUP_SETKEYS) {
4366 if (group->GKeyDoneStations == 0)
4367 wpa_group_setkeysdone(wpa_auth, group);
4368 else if (group->GTKReKey)
4369 wpa_group_setkeys(wpa_auth, group);
4370 }
4371}
4372
4373
4374static int wpa_sm_step(struct wpa_state_machine *sm)
4375{
Hai Shalomfdcde762020-04-02 11:19:20 -07004376 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004377 return 0;
4378
4379 if (sm->in_step_loop) {
4380 /* This should not happen, but if it does, make sure we do not
4381 * end up freeing the state machine too early by exiting the
4382 * recursive call. */
4383 wpa_printf(MSG_ERROR, "WPA: wpa_sm_step() called recursively");
4384 return 0;
4385 }
4386
4387 sm->in_step_loop = 1;
4388 do {
4389 if (sm->pending_deinit)
4390 break;
4391
Hai Shalome21d4e82020-04-29 16:34:06 -07004392 sm->changed = false;
4393 sm->wpa_auth->group->changed = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004394
4395 SM_STEP_RUN(WPA_PTK);
4396 if (sm->pending_deinit)
4397 break;
4398 SM_STEP_RUN(WPA_PTK_GROUP);
4399 if (sm->pending_deinit)
4400 break;
4401 wpa_group_sm_step(sm->wpa_auth, sm->group);
4402 } while (sm->changed || sm->wpa_auth->group->changed);
4403 sm->in_step_loop = 0;
4404
4405 if (sm->pending_deinit) {
Hai Shalomfdcde762020-04-02 11:19:20 -07004406 wpa_printf(MSG_DEBUG,
4407 "WPA: Completing pending STA state machine deinit for "
4408 MACSTR, MAC2STR(sm->addr));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004409 wpa_free_sta_sm(sm);
4410 return 1;
4411 }
4412 return 0;
4413}
4414
4415
4416static void wpa_sm_call_step(void *eloop_ctx, void *timeout_ctx)
4417{
4418 struct wpa_state_machine *sm = eloop_ctx;
4419 wpa_sm_step(sm);
4420}
4421
4422
4423void wpa_auth_sm_notify(struct wpa_state_machine *sm)
4424{
Hai Shalomfdcde762020-04-02 11:19:20 -07004425 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004426 return;
4427 eloop_register_timeout(0, 0, wpa_sm_call_step, sm, NULL);
4428}
4429
4430
4431void wpa_gtk_rekey(struct wpa_authenticator *wpa_auth)
4432{
4433 int tmp, i;
4434 struct wpa_group *group;
4435
Hai Shalomfdcde762020-04-02 11:19:20 -07004436 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004437 return;
4438
4439 group = wpa_auth->group;
4440
4441 for (i = 0; i < 2; i++) {
4442 tmp = group->GM;
4443 group->GM = group->GN;
4444 group->GN = tmp;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004445 tmp = group->GM_igtk;
4446 group->GM_igtk = group->GN_igtk;
4447 group->GN_igtk = tmp;
Hai Shalomfdcde762020-04-02 11:19:20 -07004448 tmp = group->GM_bigtk;
4449 group->GM_bigtk = group->GN_bigtk;
4450 group->GN_bigtk = tmp;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004451 wpa_gtk_update(wpa_auth, group);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004452 wpa_group_config_group_keys(wpa_auth, group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004453 }
4454}
4455
4456
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004457static const char * wpa_bool_txt(int val)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004458{
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004459 return val ? "TRUE" : "FALSE";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004460}
4461
4462
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004463#define RSN_SUITE "%02x-%02x-%02x-%d"
4464#define RSN_SUITE_ARG(s) \
4465((s) >> 24) & 0xff, ((s) >> 16) & 0xff, ((s) >> 8) & 0xff, (s) & 0xff
4466
4467int wpa_get_mib(struct wpa_authenticator *wpa_auth, char *buf, size_t buflen)
4468{
Hai Shalomfdcde762020-04-02 11:19:20 -07004469 struct wpa_auth_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004470 int len = 0, ret;
4471 char pmkid_txt[PMKID_LEN * 2 + 1];
4472#ifdef CONFIG_RSN_PREAUTH
4473 const int preauth = 1;
4474#else /* CONFIG_RSN_PREAUTH */
4475 const int preauth = 0;
4476#endif /* CONFIG_RSN_PREAUTH */
4477
Hai Shalomfdcde762020-04-02 11:19:20 -07004478 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004479 return len;
Hai Shalomfdcde762020-04-02 11:19:20 -07004480 conf = &wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004481
4482 ret = os_snprintf(buf + len, buflen - len,
4483 "dot11RSNAOptionImplemented=TRUE\n"
4484 "dot11RSNAPreauthenticationImplemented=%s\n"
4485 "dot11RSNAEnabled=%s\n"
4486 "dot11RSNAPreauthenticationEnabled=%s\n",
4487 wpa_bool_txt(preauth),
Hai Shalomfdcde762020-04-02 11:19:20 -07004488 wpa_bool_txt(conf->wpa & WPA_PROTO_RSN),
4489 wpa_bool_txt(conf->rsn_preauth));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004490 if (os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004491 return len;
4492 len += ret;
4493
4494 wpa_snprintf_hex(pmkid_txt, sizeof(pmkid_txt),
4495 wpa_auth->dot11RSNAPMKIDUsed, PMKID_LEN);
4496
4497 ret = os_snprintf(
4498 buf + len, buflen - len,
4499 "dot11RSNAConfigVersion=%u\n"
4500 "dot11RSNAConfigPairwiseKeysSupported=9999\n"
4501 /* FIX: dot11RSNAConfigGroupCipher */
4502 /* FIX: dot11RSNAConfigGroupRekeyMethod */
4503 /* FIX: dot11RSNAConfigGroupRekeyTime */
4504 /* FIX: dot11RSNAConfigGroupRekeyPackets */
4505 "dot11RSNAConfigGroupRekeyStrict=%u\n"
4506 "dot11RSNAConfigGroupUpdateCount=%u\n"
4507 "dot11RSNAConfigPairwiseUpdateCount=%u\n"
4508 "dot11RSNAConfigGroupCipherSize=%u\n"
4509 "dot11RSNAConfigPMKLifetime=%u\n"
4510 "dot11RSNAConfigPMKReauthThreshold=%u\n"
4511 "dot11RSNAConfigNumberOfPTKSAReplayCounters=0\n"
4512 "dot11RSNAConfigSATimeout=%u\n"
4513 "dot11RSNAAuthenticationSuiteSelected=" RSN_SUITE "\n"
4514 "dot11RSNAPairwiseCipherSelected=" RSN_SUITE "\n"
4515 "dot11RSNAGroupCipherSelected=" RSN_SUITE "\n"
4516 "dot11RSNAPMKIDUsed=%s\n"
4517 "dot11RSNAAuthenticationSuiteRequested=" RSN_SUITE "\n"
4518 "dot11RSNAPairwiseCipherRequested=" RSN_SUITE "\n"
4519 "dot11RSNAGroupCipherRequested=" RSN_SUITE "\n"
4520 "dot11RSNATKIPCounterMeasuresInvoked=%u\n"
4521 "dot11RSNA4WayHandshakeFailures=%u\n"
4522 "dot11RSNAConfigNumberOfGTKSAReplayCounters=0\n",
4523 RSN_VERSION,
Hai Shalomfdcde762020-04-02 11:19:20 -07004524 !!conf->wpa_strict_rekey,
4525 conf->wpa_group_update_count,
4526 conf->wpa_pairwise_update_count,
4527 wpa_cipher_key_len(conf->wpa_group) * 8,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004528 dot11RSNAConfigPMKLifetime,
4529 dot11RSNAConfigPMKReauthThreshold,
4530 dot11RSNAConfigSATimeout,
4531 RSN_SUITE_ARG(wpa_auth->dot11RSNAAuthenticationSuiteSelected),
4532 RSN_SUITE_ARG(wpa_auth->dot11RSNAPairwiseCipherSelected),
4533 RSN_SUITE_ARG(wpa_auth->dot11RSNAGroupCipherSelected),
4534 pmkid_txt,
4535 RSN_SUITE_ARG(wpa_auth->dot11RSNAAuthenticationSuiteRequested),
4536 RSN_SUITE_ARG(wpa_auth->dot11RSNAPairwiseCipherRequested),
4537 RSN_SUITE_ARG(wpa_auth->dot11RSNAGroupCipherRequested),
4538 wpa_auth->dot11RSNATKIPCounterMeasuresInvoked,
4539 wpa_auth->dot11RSNA4WayHandshakeFailures);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004540 if (os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004541 return len;
4542 len += ret;
4543
4544 /* TODO: dot11RSNAConfigPairwiseCiphersTable */
4545 /* TODO: dot11RSNAConfigAuthenticationSuitesTable */
4546
4547 /* Private MIB */
4548 ret = os_snprintf(buf + len, buflen - len, "hostapdWPAGroupState=%d\n",
4549 wpa_auth->group->wpa_group_state);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004550 if (os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004551 return len;
4552 len += ret;
4553
4554 return len;
4555}
4556
4557
4558int wpa_get_mib_sta(struct wpa_state_machine *sm, char *buf, size_t buflen)
4559{
4560 int len = 0, ret;
4561 u32 pairwise = 0;
4562
Hai Shalomfdcde762020-04-02 11:19:20 -07004563 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004564 return 0;
4565
4566 /* TODO: FF-FF-FF-FF-FF-FF entry for broadcast/multicast stats */
4567
4568 /* dot11RSNAStatsEntry */
4569
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07004570 pairwise = wpa_cipher_to_suite(sm->wpa == WPA_VERSION_WPA2 ?
4571 WPA_PROTO_RSN : WPA_PROTO_WPA,
4572 sm->pairwise);
4573 if (pairwise == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004574 return 0;
4575
4576 ret = os_snprintf(
4577 buf + len, buflen - len,
4578 /* TODO: dot11RSNAStatsIndex */
4579 "dot11RSNAStatsSTAAddress=" MACSTR "\n"
4580 "dot11RSNAStatsVersion=1\n"
4581 "dot11RSNAStatsSelectedPairwiseCipher=" RSN_SUITE "\n"
4582 /* TODO: dot11RSNAStatsTKIPICVErrors */
4583 "dot11RSNAStatsTKIPLocalMICFailures=%u\n"
4584 "dot11RSNAStatsTKIPRemoteMICFailures=%u\n"
4585 /* TODO: dot11RSNAStatsCCMPReplays */
4586 /* TODO: dot11RSNAStatsCCMPDecryptErrors */
4587 /* TODO: dot11RSNAStatsTKIPReplays */,
4588 MAC2STR(sm->addr),
4589 RSN_SUITE_ARG(pairwise),
4590 sm->dot11RSNAStatsTKIPLocalMICFailures,
4591 sm->dot11RSNAStatsTKIPRemoteMICFailures);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004592 if (os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004593 return len;
4594 len += ret;
4595
4596 /* Private MIB */
4597 ret = os_snprintf(buf + len, buflen - len,
Hai Shalomc3565922019-10-28 11:58:20 -07004598 "wpa=%d\n"
4599 "AKMSuiteSelector=" RSN_SUITE "\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004600 "hostapdWPAPTKState=%d\n"
4601 "hostapdWPAPTKGroupState=%d\n",
Hai Shalomc3565922019-10-28 11:58:20 -07004602 sm->wpa,
4603 RSN_SUITE_ARG(wpa_akm_to_suite(sm->wpa_key_mgmt)),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004604 sm->wpa_ptk_state,
4605 sm->wpa_ptk_group_state);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004606 if (os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004607 return len;
4608 len += ret;
4609
4610 return len;
4611}
4612
4613
4614void wpa_auth_countermeasures_start(struct wpa_authenticator *wpa_auth)
4615{
4616 if (wpa_auth)
4617 wpa_auth->dot11RSNATKIPCounterMeasuresInvoked++;
4618}
4619
4620
4621int wpa_auth_pairwise_set(struct wpa_state_machine *sm)
4622{
4623 return sm && sm->pairwise_set;
4624}
4625
4626
4627int wpa_auth_get_pairwise(struct wpa_state_machine *sm)
4628{
4629 return sm->pairwise;
4630}
4631
4632
Hai Shalom74f70d42019-02-11 14:42:39 -08004633const u8 * wpa_auth_get_pmk(struct wpa_state_machine *sm, int *len)
4634{
4635 if (!sm)
4636 return NULL;
4637 *len = sm->pmk_len;
4638 return sm->PMK;
4639}
4640
4641
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004642int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm)
4643{
Hai Shalomfdcde762020-04-02 11:19:20 -07004644 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004645 return -1;
4646 return sm->wpa_key_mgmt;
4647}
4648
4649
4650int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm)
4651{
Hai Shalomfdcde762020-04-02 11:19:20 -07004652 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004653 return 0;
4654 return sm->wpa;
4655}
4656
4657
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02004658int wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm)
4659{
4660 if (!sm || !wpa_key_mgmt_ft(sm->wpa_key_mgmt))
4661 return 0;
4662 return sm->tk_already_set;
4663}
4664
4665
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004666int wpa_auth_sta_fils_tk_already_set(struct wpa_state_machine *sm)
4667{
4668 if (!sm || !wpa_key_mgmt_fils(sm->wpa_key_mgmt))
4669 return 0;
4670 return sm->tk_already_set;
4671}
4672
4673
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004674int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm,
4675 struct rsn_pmksa_cache_entry *entry)
4676{
Hai Shalomfdcde762020-04-02 11:19:20 -07004677 if (!sm || sm->pmksa != entry)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004678 return -1;
4679 sm->pmksa = NULL;
4680 return 0;
4681}
4682
4683
4684struct rsn_pmksa_cache_entry *
4685wpa_auth_sta_get_pmksa(struct wpa_state_machine *sm)
4686{
4687 return sm ? sm->pmksa : NULL;
4688}
4689
4690
4691void wpa_auth_sta_local_mic_failure_report(struct wpa_state_machine *sm)
4692{
4693 if (sm)
4694 sm->dot11RSNAStatsTKIPLocalMICFailures++;
4695}
4696
4697
4698const u8 * wpa_auth_get_wpa_ie(struct wpa_authenticator *wpa_auth, size_t *len)
4699{
Hai Shalomfdcde762020-04-02 11:19:20 -07004700 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004701 return NULL;
4702 *len = wpa_auth->wpa_ie_len;
4703 return wpa_auth->wpa_ie;
4704}
4705
4706
4707int wpa_auth_pmksa_add(struct wpa_state_machine *sm, const u8 *pmk,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004708 unsigned int pmk_len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004709 int session_timeout, struct eapol_state_machine *eapol)
4710{
Hai Shalomfdcde762020-04-02 11:19:20 -07004711 if (!sm || sm->wpa != WPA_VERSION_WPA2 ||
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07004712 sm->wpa_auth->conf.disable_pmksa_caching)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004713 return -1;
4714
Hai Shalom81f62d82019-07-22 12:10:00 -07004715#ifdef CONFIG_IEEE80211R_AP
4716 if (pmk_len >= 2 * PMK_LEN && wpa_key_mgmt_ft(sm->wpa_key_mgmt) &&
4717 wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) &&
4718 !wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) {
4719 /* Cache MPMK/XXKey instead of initial part from MSK */
4720 pmk = pmk + PMK_LEN;
4721 pmk_len = PMK_LEN;
4722 } else
4723#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004724 if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004725 if (pmk_len > PMK_LEN_SUITE_B_192)
4726 pmk_len = PMK_LEN_SUITE_B_192;
4727 } else if (pmk_len > PMK_LEN) {
4728 pmk_len = PMK_LEN;
4729 }
4730
Hai Shalom81f62d82019-07-22 12:10:00 -07004731 wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK", pmk, pmk_len);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004732 if (pmksa_cache_auth_add(sm->wpa_auth->pmksa, pmk, pmk_len, NULL,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004733 sm->PTK.kck, sm->PTK.kck_len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004734 sm->wpa_auth->addr, sm->addr, session_timeout,
4735 eapol, sm->wpa_key_mgmt))
4736 return 0;
4737
4738 return -1;
4739}
4740
4741
4742int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth,
4743 const u8 *pmk, size_t len, const u8 *sta_addr,
4744 int session_timeout,
4745 struct eapol_state_machine *eapol)
4746{
Hai Shalomfdcde762020-04-02 11:19:20 -07004747 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004748 return -1;
4749
Hai Shalom81f62d82019-07-22 12:10:00 -07004750 wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK from preauth", pmk, len);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004751 if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, len, NULL,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004752 NULL, 0,
4753 wpa_auth->addr,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004754 sta_addr, session_timeout, eapol,
4755 WPA_KEY_MGMT_IEEE8021X))
4756 return 0;
4757
4758 return -1;
4759}
4760
4761
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004762int wpa_auth_pmksa_add_sae(struct wpa_authenticator *wpa_auth, const u8 *addr,
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004763 const u8 *pmk, const u8 *pmkid)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004764{
4765 if (wpa_auth->conf.disable_pmksa_caching)
4766 return -1;
4767
Hai Shalom81f62d82019-07-22 12:10:00 -07004768 wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK from SAE", pmk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004769 if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, PMK_LEN, pmkid,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004770 NULL, 0,
4771 wpa_auth->addr, addr, 0, NULL,
4772 WPA_KEY_MGMT_SAE))
4773 return 0;
4774
4775 return -1;
4776}
4777
4778
Roshan Pius3a1667e2018-07-03 15:17:14 -07004779void wpa_auth_add_sae_pmkid(struct wpa_state_machine *sm, const u8 *pmkid)
4780{
4781 os_memcpy(sm->pmkid, pmkid, PMKID_LEN);
4782 sm->pmkid_set = 1;
4783}
4784
4785
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004786int wpa_auth_pmksa_add2(struct wpa_authenticator *wpa_auth, const u8 *addr,
4787 const u8 *pmk, size_t pmk_len, const u8 *pmkid,
4788 int session_timeout, int akmp)
4789{
4790 if (wpa_auth->conf.disable_pmksa_caching)
4791 return -1;
4792
Hai Shalom81f62d82019-07-22 12:10:00 -07004793 wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK (2)", pmk, PMK_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004794 if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, pmk_len, pmkid,
4795 NULL, 0, wpa_auth->addr, addr, session_timeout,
4796 NULL, akmp))
4797 return 0;
4798
4799 return -1;
4800}
4801
4802
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004803void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth,
4804 const u8 *sta_addr)
4805{
4806 struct rsn_pmksa_cache_entry *pmksa;
4807
Hai Shalomfdcde762020-04-02 11:19:20 -07004808 if (!wpa_auth || !wpa_auth->pmksa)
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004809 return;
4810 pmksa = pmksa_cache_auth_get(wpa_auth->pmksa, sta_addr, NULL);
4811 if (pmksa) {
4812 wpa_printf(MSG_DEBUG, "WPA: Remove PMKSA cache entry for "
4813 MACSTR " based on request", MAC2STR(sta_addr));
4814 pmksa_cache_free_entry(wpa_auth->pmksa, pmksa);
4815 }
4816}
4817
4818
Dmitry Shmidte4663042016-04-04 10:07:49 -07004819int wpa_auth_pmksa_list(struct wpa_authenticator *wpa_auth, char *buf,
4820 size_t len)
4821{
4822 if (!wpa_auth || !wpa_auth->pmksa)
4823 return 0;
4824 return pmksa_cache_auth_list(wpa_auth->pmksa, buf, len);
4825}
4826
4827
4828void wpa_auth_pmksa_flush(struct wpa_authenticator *wpa_auth)
4829{
4830 if (wpa_auth && wpa_auth->pmksa)
4831 pmksa_cache_auth_flush(wpa_auth->pmksa);
4832}
4833
4834
Paul Stewart092955c2017-02-06 09:13:09 -08004835#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
4836#ifdef CONFIG_MESH
4837
4838int wpa_auth_pmksa_list_mesh(struct wpa_authenticator *wpa_auth, const u8 *addr,
4839 char *buf, size_t len)
4840{
4841 if (!wpa_auth || !wpa_auth->pmksa)
4842 return 0;
4843
4844 return pmksa_cache_auth_list_mesh(wpa_auth->pmksa, addr, buf, len);
4845}
4846
4847
4848struct rsn_pmksa_cache_entry *
4849wpa_auth_pmksa_create_entry(const u8 *aa, const u8 *spa, const u8 *pmk,
4850 const u8 *pmkid, int expiration)
4851{
4852 struct rsn_pmksa_cache_entry *entry;
4853 struct os_reltime now;
4854
4855 entry = pmksa_cache_auth_create_entry(pmk, PMK_LEN, pmkid, NULL, 0, aa,
4856 spa, 0, NULL, WPA_KEY_MGMT_SAE);
4857 if (!entry)
4858 return NULL;
4859
4860 os_get_reltime(&now);
4861 entry->expiration = now.sec + expiration;
4862 return entry;
4863}
4864
4865
4866int wpa_auth_pmksa_add_entry(struct wpa_authenticator *wpa_auth,
4867 struct rsn_pmksa_cache_entry *entry)
4868{
4869 int ret;
4870
4871 if (!wpa_auth || !wpa_auth->pmksa)
4872 return -1;
4873
4874 ret = pmksa_cache_auth_add_entry(wpa_auth->pmksa, entry);
4875 if (ret < 0)
4876 wpa_printf(MSG_DEBUG,
4877 "RSN: Failed to store external PMKSA cache for "
4878 MACSTR, MAC2STR(entry->spa));
4879
4880 return ret;
4881}
4882
4883#endif /* CONFIG_MESH */
4884#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
4885
4886
Dmitry Shmidte4663042016-04-04 10:07:49 -07004887struct rsn_pmksa_cache_entry *
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004888wpa_auth_pmksa_get(struct wpa_authenticator *wpa_auth, const u8 *sta_addr,
4889 const u8 *pmkid)
Dmitry Shmidte4663042016-04-04 10:07:49 -07004890{
4891 if (!wpa_auth || !wpa_auth->pmksa)
4892 return NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004893 return pmksa_cache_auth_get(wpa_auth->pmksa, sta_addr, pmkid);
Dmitry Shmidte4663042016-04-04 10:07:49 -07004894}
4895
4896
4897void wpa_auth_pmksa_set_to_sm(struct rsn_pmksa_cache_entry *pmksa,
4898 struct wpa_state_machine *sm,
4899 struct wpa_authenticator *wpa_auth,
4900 u8 *pmkid, u8 *pmk)
4901{
4902 if (!sm)
4903 return;
4904
4905 sm->pmksa = pmksa;
4906 os_memcpy(pmk, pmksa->pmk, PMK_LEN);
4907 os_memcpy(pmkid, pmksa->pmkid, PMKID_LEN);
4908 os_memcpy(wpa_auth->dot11RSNAPMKIDUsed, pmksa->pmkid, PMKID_LEN);
4909}
4910
4911
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004912/*
4913 * Remove and free the group from wpa_authenticator. This is triggered by a
4914 * callback to make sure nobody is currently iterating the group list while it
4915 * gets modified.
4916 */
4917static void wpa_group_free(struct wpa_authenticator *wpa_auth,
4918 struct wpa_group *group)
4919{
4920 struct wpa_group *prev = wpa_auth->group;
4921
4922 wpa_printf(MSG_DEBUG, "WPA: Remove group state machine for VLAN-ID %d",
4923 group->vlan_id);
4924
4925 while (prev) {
4926 if (prev->next == group) {
4927 /* This never frees the special first group as needed */
4928 prev->next = group->next;
4929 os_free(group);
4930 break;
4931 }
4932 prev = prev->next;
4933 }
4934
4935}
4936
4937
4938/* Increase the reference counter for group */
4939static void wpa_group_get(struct wpa_authenticator *wpa_auth,
4940 struct wpa_group *group)
4941{
4942 /* Skip the special first group */
4943 if (wpa_auth->group == group)
4944 return;
4945
4946 group->references++;
4947}
4948
4949
4950/* Decrease the reference counter and maybe free the group */
4951static void wpa_group_put(struct wpa_authenticator *wpa_auth,
4952 struct wpa_group *group)
4953{
4954 /* Skip the special first group */
4955 if (wpa_auth->group == group)
4956 return;
4957
4958 group->references--;
4959 if (group->references)
4960 return;
4961 wpa_group_free(wpa_auth, group);
4962}
4963
4964
4965/*
4966 * Add a group that has its references counter set to zero. Caller needs to
4967 * call wpa_group_get() on the return value to mark the entry in use.
4968 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004969static struct wpa_group *
4970wpa_auth_add_group(struct wpa_authenticator *wpa_auth, int vlan_id)
4971{
4972 struct wpa_group *group;
4973
Hai Shalomfdcde762020-04-02 11:19:20 -07004974 if (!wpa_auth || !wpa_auth->group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004975 return NULL;
4976
4977 wpa_printf(MSG_DEBUG, "WPA: Add group state machine for VLAN-ID %d",
4978 vlan_id);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004979 group = wpa_group_init(wpa_auth, vlan_id, 0);
Hai Shalomfdcde762020-04-02 11:19:20 -07004980 if (!group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004981 return NULL;
4982
4983 group->next = wpa_auth->group->next;
4984 wpa_auth->group->next = group;
4985
4986 return group;
4987}
4988
4989
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004990/*
4991 * Enforce that the group state machine for the VLAN is running, increase
4992 * reference counter as interface is up. References might have been increased
4993 * even if a negative value is returned.
4994 * Returns: -1 on error (group missing, group already failed); otherwise, 0
4995 */
4996int wpa_auth_ensure_group(struct wpa_authenticator *wpa_auth, int vlan_id)
4997{
4998 struct wpa_group *group;
4999
Hai Shalomfdcde762020-04-02 11:19:20 -07005000 if (!wpa_auth)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005001 return 0;
5002
5003 group = wpa_auth->group;
5004 while (group) {
5005 if (group->vlan_id == vlan_id)
5006 break;
5007 group = group->next;
5008 }
5009
Hai Shalomfdcde762020-04-02 11:19:20 -07005010 if (!group) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005011 group = wpa_auth_add_group(wpa_auth, vlan_id);
Hai Shalomfdcde762020-04-02 11:19:20 -07005012 if (!group)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005013 return -1;
5014 }
5015
5016 wpa_printf(MSG_DEBUG,
5017 "WPA: Ensure group state machine running for VLAN ID %d",
5018 vlan_id);
5019
5020 wpa_group_get(wpa_auth, group);
5021 group->num_setup_iface++;
5022
5023 if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
5024 return -1;
5025
5026 return 0;
5027}
5028
5029
5030/*
5031 * Decrease reference counter, expected to be zero afterwards.
5032 * returns: -1 on error (group not found, group in fail state)
5033 * -2 if wpa_group is still referenced
5034 * 0 else
5035 */
5036int wpa_auth_release_group(struct wpa_authenticator *wpa_auth, int vlan_id)
5037{
5038 struct wpa_group *group;
5039 int ret = 0;
5040
Hai Shalomfdcde762020-04-02 11:19:20 -07005041 if (!wpa_auth)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005042 return 0;
5043
5044 group = wpa_auth->group;
5045 while (group) {
5046 if (group->vlan_id == vlan_id)
5047 break;
5048 group = group->next;
5049 }
5050
Hai Shalomfdcde762020-04-02 11:19:20 -07005051 if (!group)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005052 return -1;
5053
5054 wpa_printf(MSG_DEBUG,
5055 "WPA: Try stopping group state machine for VLAN ID %d",
5056 vlan_id);
5057
5058 if (group->num_setup_iface <= 0) {
5059 wpa_printf(MSG_ERROR,
5060 "WPA: wpa_auth_release_group called more often than wpa_auth_ensure_group for VLAN ID %d, skipping.",
5061 vlan_id);
5062 return -1;
5063 }
5064 group->num_setup_iface--;
5065
5066 if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
5067 ret = -1;
5068
5069 if (group->references > 1) {
5070 wpa_printf(MSG_DEBUG,
5071 "WPA: Cannot stop group state machine for VLAN ID %d as references are still hold",
5072 vlan_id);
5073 ret = -2;
5074 }
5075
5076 wpa_group_put(wpa_auth, group);
5077
5078 return ret;
5079}
5080
5081
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005082int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id)
5083{
5084 struct wpa_group *group;
5085
Hai Shalomfdcde762020-04-02 11:19:20 -07005086 if (!sm || !sm->wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005087 return 0;
5088
5089 group = sm->wpa_auth->group;
5090 while (group) {
5091 if (group->vlan_id == vlan_id)
5092 break;
5093 group = group->next;
5094 }
5095
Hai Shalomfdcde762020-04-02 11:19:20 -07005096 if (!group) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005097 group = wpa_auth_add_group(sm->wpa_auth, vlan_id);
Hai Shalomfdcde762020-04-02 11:19:20 -07005098 if (!group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005099 return -1;
5100 }
5101
5102 if (sm->group == group)
5103 return 0;
5104
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005105 if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
5106 return -1;
5107
Hai Shalomfdcde762020-04-02 11:19:20 -07005108 wpa_printf(MSG_DEBUG, "WPA: Moving STA " MACSTR
5109 " to use group state machine for VLAN ID %d",
5110 MAC2STR(sm->addr), vlan_id);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005111
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005112 wpa_group_get(sm->wpa_auth, group);
5113 wpa_group_put(sm->wpa_auth, sm->group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005114 sm->group = group;
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005115
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005116 return 0;
5117}
5118
5119
5120void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth,
5121 struct wpa_state_machine *sm, int ack)
5122{
Hai Shalomfdcde762020-04-02 11:19:20 -07005123 if (!wpa_auth || !sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005124 return;
5125 wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key TX status for STA " MACSTR
5126 " ack=%d", MAC2STR(sm->addr), ack);
5127 if (sm->pending_1_of_4_timeout && ack) {
5128 /*
5129 * Some deployed supplicant implementations update their SNonce
5130 * for each EAPOL-Key 2/4 message even within the same 4-way
5131 * handshake and then fail to use the first SNonce when
5132 * deriving the PTK. This results in unsuccessful 4-way
5133 * handshake whenever the relatively short initial timeout is
5134 * reached and EAPOL-Key 1/4 is retransmitted. Try to work
5135 * around this by increasing the timeout now that we know that
5136 * the station has received the frame.
5137 */
5138 int timeout_ms = eapol_key_timeout_subseq;
Hai Shalomfdcde762020-04-02 11:19:20 -07005139 wpa_printf(MSG_DEBUG,
5140 "WPA: Increase initial EAPOL-Key 1/4 timeout by %u ms because of acknowledged frame",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005141 timeout_ms);
5142 eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm);
5143 eloop_register_timeout(timeout_ms / 1000,
5144 (timeout_ms % 1000) * 1000,
5145 wpa_send_eapol_timeout, wpa_auth, sm);
5146 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005147
5148#ifdef CONFIG_TESTING_OPTIONS
5149 if (sm->eapol_status_cb) {
5150 sm->eapol_status_cb(sm->eapol_status_cb_ctx1,
5151 sm->eapol_status_cb_ctx2);
5152 sm->eapol_status_cb = NULL;
5153 }
5154#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005155}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005156
5157
5158int wpa_auth_uses_sae(struct wpa_state_machine *sm)
5159{
Hai Shalomfdcde762020-04-02 11:19:20 -07005160 if (!sm)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005161 return 0;
5162 return wpa_key_mgmt_sae(sm->wpa_key_mgmt);
5163}
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005164
5165
5166int wpa_auth_uses_ft_sae(struct wpa_state_machine *sm)
5167{
Hai Shalomfdcde762020-04-02 11:19:20 -07005168 if (!sm)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005169 return 0;
5170 return sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_SAE;
5171}
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08005172
5173
5174#ifdef CONFIG_P2P
5175int wpa_auth_get_ip_addr(struct wpa_state_machine *sm, u8 *addr)
5176{
Hai Shalomfdcde762020-04-02 11:19:20 -07005177 if (!sm || WPA_GET_BE32(sm->ip_addr) == 0)
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08005178 return -1;
5179 os_memcpy(addr, sm->ip_addr, 4);
5180 return 0;
5181}
5182#endif /* CONFIG_P2P */
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08005183
5184
5185int wpa_auth_radius_das_disconnect_pmksa(struct wpa_authenticator *wpa_auth,
5186 struct radius_das_attrs *attr)
5187{
5188 return pmksa_cache_auth_radius_das_disconnect(wpa_auth->pmksa, attr);
5189}
Dmitry Shmidt7f656022015-02-25 14:36:37 -08005190
5191
5192void wpa_auth_reconfig_group_keys(struct wpa_authenticator *wpa_auth)
5193{
5194 struct wpa_group *group;
5195
5196 if (!wpa_auth)
5197 return;
5198 for (group = wpa_auth->group; group; group = group->next)
5199 wpa_group_config_group_keys(wpa_auth, group);
5200}
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005201
5202
5203#ifdef CONFIG_FILS
5204
5205struct wpa_auth_fils_iter_data {
5206 struct wpa_authenticator *auth;
5207 const u8 *cache_id;
5208 struct rsn_pmksa_cache_entry *pmksa;
5209 const u8 *spa;
5210 const u8 *pmkid;
5211};
5212
5213
5214static int wpa_auth_fils_iter(struct wpa_authenticator *a, void *ctx)
5215{
5216 struct wpa_auth_fils_iter_data *data = ctx;
5217
5218 if (a == data->auth || !a->conf.fils_cache_id_set ||
5219 os_memcmp(a->conf.fils_cache_id, data->cache_id,
5220 FILS_CACHE_ID_LEN) != 0)
5221 return 0;
5222 data->pmksa = pmksa_cache_auth_get(a->pmksa, data->spa, data->pmkid);
5223 return data->pmksa != NULL;
5224}
5225
5226
5227struct rsn_pmksa_cache_entry *
5228wpa_auth_pmksa_get_fils_cache_id(struct wpa_authenticator *wpa_auth,
5229 const u8 *sta_addr, const u8 *pmkid)
5230{
5231 struct wpa_auth_fils_iter_data idata;
5232
5233 if (!wpa_auth->conf.fils_cache_id_set)
5234 return NULL;
5235 idata.auth = wpa_auth;
5236 idata.cache_id = wpa_auth->conf.fils_cache_id;
5237 idata.pmksa = NULL;
5238 idata.spa = sta_addr;
5239 idata.pmkid = pmkid;
5240 wpa_auth_for_each_auth(wpa_auth, wpa_auth_fils_iter, &idata);
5241 return idata.pmksa;
5242}
5243
5244
5245#ifdef CONFIG_IEEE80211R_AP
Roshan Pius3a1667e2018-07-03 15:17:14 -07005246int wpa_auth_write_fte(struct wpa_authenticator *wpa_auth, int use_sha384,
5247 u8 *buf, size_t len)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005248{
5249 struct wpa_auth_config *conf = &wpa_auth->conf;
5250
Roshan Pius3a1667e2018-07-03 15:17:14 -07005251 return wpa_write_ftie(conf, use_sha384, conf->r0_key_holder,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005252 conf->r0_key_holder_len,
Hai Shalomfdcde762020-04-02 11:19:20 -07005253 NULL, NULL, buf, len, NULL, 0, 0);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005254}
5255#endif /* CONFIG_IEEE80211R_AP */
5256
5257
5258void wpa_auth_get_fils_aead_params(struct wpa_state_machine *sm,
5259 u8 *fils_anonce, u8 *fils_snonce,
5260 u8 *fils_kek, size_t *fils_kek_len)
5261{
5262 os_memcpy(fils_anonce, sm->ANonce, WPA_NONCE_LEN);
5263 os_memcpy(fils_snonce, sm->SNonce, WPA_NONCE_LEN);
5264 os_memcpy(fils_kek, sm->PTK.kek, WPA_KEK_MAX_LEN);
5265 *fils_kek_len = sm->PTK.kek_len;
5266}
5267
Hai Shalom81f62d82019-07-22 12:10:00 -07005268
5269void wpa_auth_add_fils_pmk_pmkid(struct wpa_state_machine *sm, const u8 *pmk,
5270 size_t pmk_len, const u8 *pmkid)
5271{
5272 os_memcpy(sm->PMK, pmk, pmk_len);
5273 sm->pmk_len = pmk_len;
5274 os_memcpy(sm->pmkid, pmkid, PMKID_LEN);
5275 sm->pmkid_set = 1;
5276}
5277
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005278#endif /* CONFIG_FILS */
5279
5280
Hai Shalom021b0b52019-04-10 11:17:58 -07005281void wpa_auth_set_auth_alg(struct wpa_state_machine *sm, u16 auth_alg)
5282{
5283 if (sm)
5284 sm->auth_alg = auth_alg;
5285}
5286
5287
5288#ifdef CONFIG_DPP2
5289void wpa_auth_set_dpp_z(struct wpa_state_machine *sm, const struct wpabuf *z)
5290{
5291 if (sm) {
5292 wpabuf_clear_free(sm->dpp_z);
5293 sm->dpp_z = z ? wpabuf_dup(z) : NULL;
5294 }
5295}
5296#endif /* CONFIG_DPP2 */
5297
5298
Hai Shalom899fcc72020-10-19 14:38:18 -07005299void wpa_auth_set_transition_disable(struct wpa_authenticator *wpa_auth,
5300 u8 val)
5301{
5302 if (wpa_auth)
5303 wpa_auth->conf.transition_disable = val;
5304}
5305
5306
Roshan Pius3a1667e2018-07-03 15:17:14 -07005307#ifdef CONFIG_TESTING_OPTIONS
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005308
5309int wpa_auth_resend_m1(struct wpa_state_machine *sm, int change_anonce,
5310 void (*cb)(void *ctx1, void *ctx2),
5311 void *ctx1, void *ctx2)
5312{
5313 const u8 *anonce = sm->ANonce;
5314 u8 anonce_buf[WPA_NONCE_LEN];
5315
5316 if (change_anonce) {
5317 if (random_get_bytes(anonce_buf, WPA_NONCE_LEN))
5318 return -1;
5319 anonce = anonce_buf;
5320 }
5321
5322 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
5323 "sending 1/4 msg of 4-Way Handshake (TESTING)");
5324 wpa_send_eapol(sm->wpa_auth, sm,
5325 WPA_KEY_INFO_ACK | WPA_KEY_INFO_KEY_TYPE, NULL,
5326 anonce, NULL, 0, 0, 0);
5327 return 0;
5328}
5329
5330
5331int wpa_auth_resend_m3(struct wpa_state_machine *sm,
5332 void (*cb)(void *ctx1, void *ctx2),
5333 void *ctx1, void *ctx2)
5334{
Roshan Pius3a1667e2018-07-03 15:17:14 -07005335 u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde, *pos;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005336 u8 *opos;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005337 size_t gtk_len, kde_len;
Hai Shalom899fcc72020-10-19 14:38:18 -07005338 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005339 struct wpa_group *gsm = sm->group;
5340 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07005341 int wpa_ie_len, secure, gtkidx, encr = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07005342 u8 hdr[2];
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005343
5344 /* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, [MDIE],
Hai Shalomfdcde762020-04-02 11:19:20 -07005345 GTK[GN], IGTK, [BIGTK], [FTIE], [TIE * 2])
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005346 */
5347
5348 /* Use 0 RSC */
5349 os_memset(rsc, 0, WPA_KEY_RSC_LEN);
5350 /* If FT is used, wpa_auth->wpa_ie includes both RSNIE and MDIE */
5351 wpa_ie = sm->wpa_auth->wpa_ie;
5352 wpa_ie_len = sm->wpa_auth->wpa_ie_len;
5353 if (sm->wpa == WPA_VERSION_WPA &&
5354 (sm->wpa_auth->conf.wpa & WPA_PROTO_RSN) &&
5355 wpa_ie_len > wpa_ie[1] + 2 && wpa_ie[0] == WLAN_EID_RSN) {
5356 /* WPA-only STA, remove RSN IE and possible MDIE */
5357 wpa_ie = wpa_ie + wpa_ie[1] + 2;
5358 if (wpa_ie[0] == WLAN_EID_MOBILITY_DOMAIN)
5359 wpa_ie = wpa_ie + wpa_ie[1] + 2;
5360 wpa_ie_len = wpa_ie[1] + 2;
5361 }
5362 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
5363 "sending 3/4 msg of 4-Way Handshake (TESTING)");
5364 if (sm->wpa == WPA_VERSION_WPA2) {
5365 /* WPA2 send GTK in the 4-way handshake */
5366 secure = 1;
5367 gtk = gsm->GTK[gsm->GN - 1];
5368 gtk_len = gsm->GTK_len;
Hai Shalomc3565922019-10-28 11:58:20 -07005369 gtkidx = gsm->GN;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005370 _rsc = rsc;
5371 encr = 1;
5372 } else {
5373 /* WPA does not include GTK in msg 3/4 */
5374 secure = 0;
5375 gtk = NULL;
5376 gtk_len = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005377 _rsc = NULL;
5378 if (sm->rx_eapol_key_secure) {
5379 /*
5380 * It looks like Windows 7 supplicant tries to use
5381 * Secure bit in msg 2/4 after having reported Michael
5382 * MIC failure and it then rejects the 4-way handshake
5383 * if msg 3/4 does not set Secure bit. Work around this
5384 * by setting the Secure bit here even in the case of
5385 * WPA if the supplicant used it first.
5386 */
5387 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07005388 "STA used Secure bit in WPA msg 2/4 - set Secure for 3/4 as workaround");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005389 secure = 1;
5390 }
5391 }
5392
Hai Shalom74f70d42019-02-11 14:42:39 -08005393 kde_len = wpa_ie_len + ieee80211w_kde_len(sm) + ocv_oci_len(sm);
Hai Shalomfdcde762020-04-02 11:19:20 -07005394
5395 if (sm->use_ext_key_id)
5396 kde_len += 2 + RSN_SELECTOR_LEN + 2;
5397
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005398 if (gtk)
5399 kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len;
5400#ifdef CONFIG_IEEE80211R_AP
5401 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
5402 kde_len += 2 + PMKID_LEN; /* PMKR1Name into RSN IE */
5403 kde_len += 300; /* FTIE + 2 * TIE */
5404 }
5405#endif /* CONFIG_IEEE80211R_AP */
5406 kde = os_malloc(kde_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07005407 if (!kde)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005408 return -1;
5409
5410 pos = kde;
5411 os_memcpy(pos, wpa_ie, wpa_ie_len);
5412 pos += wpa_ie_len;
5413#ifdef CONFIG_IEEE80211R_AP
5414 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
5415 int res;
5416 size_t elen;
5417
5418 elen = pos - kde;
5419 res = wpa_insert_pmkid(kde, &elen, sm->pmk_r1_name);
5420 if (res < 0) {
Hai Shalomfdcde762020-04-02 11:19:20 -07005421 wpa_printf(MSG_ERROR,
5422 "FT: Failed to insert PMKR1Name into RSN IE in EAPOL-Key data");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005423 os_free(kde);
5424 return -1;
5425 }
5426 pos -= wpa_ie_len;
5427 pos += elen;
5428 }
5429#endif /* CONFIG_IEEE80211R_AP */
Hai Shalomfdcde762020-04-02 11:19:20 -07005430 hdr[1] = 0;
5431
5432 if (sm->use_ext_key_id) {
5433 hdr[0] = sm->keyidx_active & 0x01;
5434 pos = wpa_add_kde(pos, RSN_KEY_DATA_KEYID, hdr, 2, NULL, 0);
5435 }
5436
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005437 if (gtk) {
Hai Shalomc3565922019-10-28 11:58:20 -07005438 hdr[0] = gtkidx & 0x03;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005439 pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
5440 gtk, gtk_len);
5441 }
5442 opos = pos;
5443 pos = ieee80211w_kde_add(sm, pos);
Roshan Pius3a1667e2018-07-03 15:17:14 -07005444 if (pos - opos >= 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN) {
5445 /* skip KDE header and keyid */
5446 opos += 2 + RSN_SELECTOR_LEN + 2;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005447 os_memset(opos, 0, 6); /* clear PN */
5448 }
Hai Shalom899fcc72020-10-19 14:38:18 -07005449 if (ocv_oci_add(sm, &pos, conf->oci_freq_override_eapol_m3) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -08005450 os_free(kde);
5451 return -1;
5452 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005453
5454#ifdef CONFIG_IEEE80211R_AP
5455 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
5456 int res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005457
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005458 if (sm->assoc_resp_ftie &&
5459 kde + kde_len - pos >= 2 + sm->assoc_resp_ftie[1]) {
5460 os_memcpy(pos, sm->assoc_resp_ftie,
5461 2 + sm->assoc_resp_ftie[1]);
5462 res = 2 + sm->assoc_resp_ftie[1];
5463 } else {
Roshan Pius3a1667e2018-07-03 15:17:14 -07005464 int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt);
5465
5466 res = wpa_write_ftie(conf, use_sha384,
5467 conf->r0_key_holder,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005468 conf->r0_key_holder_len,
5469 NULL, NULL, pos,
5470 kde + kde_len - pos,
Hai Shalomfdcde762020-04-02 11:19:20 -07005471 NULL, 0, 0);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005472 }
5473 if (res < 0) {
Hai Shalomfdcde762020-04-02 11:19:20 -07005474 wpa_printf(MSG_ERROR,
5475 "FT: Failed to insert FTIE into EAPOL-Key Key Data");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005476 os_free(kde);
5477 return -1;
5478 }
5479 pos += res;
5480
5481 /* TIE[ReassociationDeadline] (TU) */
5482 *pos++ = WLAN_EID_TIMEOUT_INTERVAL;
5483 *pos++ = 5;
5484 *pos++ = WLAN_TIMEOUT_REASSOC_DEADLINE;
5485 WPA_PUT_LE32(pos, conf->reassociation_deadline);
5486 pos += 4;
5487
5488 /* TIE[KeyLifetime] (seconds) */
5489 *pos++ = WLAN_EID_TIMEOUT_INTERVAL;
5490 *pos++ = 5;
5491 *pos++ = WLAN_TIMEOUT_KEY_LIFETIME;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005492 WPA_PUT_LE32(pos, conf->r0_key_lifetime);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005493 pos += 4;
5494 }
5495#endif /* CONFIG_IEEE80211R_AP */
5496
5497 wpa_send_eapol(sm->wpa_auth, sm,
5498 (secure ? WPA_KEY_INFO_SECURE : 0) |
5499 (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
5500 WPA_KEY_INFO_MIC : 0) |
5501 WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL |
5502 WPA_KEY_INFO_KEY_TYPE,
Hai Shalomc3565922019-10-28 11:58:20 -07005503 _rsc, sm->ANonce, kde, pos - kde, 0, encr);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005504 os_free(kde);
5505 return 0;
5506}
5507
5508
5509int wpa_auth_resend_group_m1(struct wpa_state_machine *sm,
5510 void (*cb)(void *ctx1, void *ctx2),
5511 void *ctx1, void *ctx2)
5512{
5513 u8 rsc[WPA_KEY_RSC_LEN];
Hai Shalom899fcc72020-10-19 14:38:18 -07005514 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005515 struct wpa_group *gsm = sm->group;
5516 const u8 *kde;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005517 u8 *kde_buf = NULL, *pos, hdr[2];
Roshan Pius3a1667e2018-07-03 15:17:14 -07005518 u8 *opos;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005519 size_t kde_len;
5520 u8 *gtk;
5521
5522 /* Send EAPOL(1, 1, 1, !Pair, G, RSC, GNonce, MIC(PTK), GTK[GN]) */
5523 os_memset(rsc, 0, WPA_KEY_RSC_LEN);
5524 /* Use 0 RSC */
5525 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
5526 "sending 1/2 msg of Group Key Handshake (TESTING)");
5527
5528 gtk = gsm->GTK[gsm->GN - 1];
5529 if (sm->wpa == WPA_VERSION_WPA2) {
5530 kde_len = 2 + RSN_SELECTOR_LEN + 2 + gsm->GTK_len +
Hai Shalom74f70d42019-02-11 14:42:39 -08005531 ieee80211w_kde_len(sm) + ocv_oci_len(sm);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005532 kde_buf = os_malloc(kde_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07005533 if (!kde_buf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005534 return -1;
5535
5536 kde = pos = kde_buf;
5537 hdr[0] = gsm->GN & 0x03;
5538 hdr[1] = 0;
5539 pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
5540 gtk, gsm->GTK_len);
5541 opos = pos;
5542 pos = ieee80211w_kde_add(sm, pos);
Roshan Pius3a1667e2018-07-03 15:17:14 -07005543 if (pos - opos >=
5544 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN) {
5545 /* skip KDE header and keyid */
5546 opos += 2 + RSN_SELECTOR_LEN + 2;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005547 os_memset(opos, 0, 6); /* clear PN */
5548 }
Hai Shalom899fcc72020-10-19 14:38:18 -07005549 if (ocv_oci_add(sm, &pos,
5550 conf->oci_freq_override_eapol_g1) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -08005551 os_free(kde_buf);
5552 return -1;
5553 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005554 kde_len = pos - kde;
5555 } else {
5556 kde = gtk;
5557 kde_len = gsm->GTK_len;
5558 }
5559
5560 sm->eapol_status_cb = cb;
5561 sm->eapol_status_cb_ctx1 = ctx1;
5562 sm->eapol_status_cb_ctx2 = ctx2;
5563
5564 wpa_send_eapol(sm->wpa_auth, sm,
5565 WPA_KEY_INFO_SECURE |
5566 (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
5567 WPA_KEY_INFO_MIC : 0) |
5568 WPA_KEY_INFO_ACK |
5569 (!sm->Pair ? WPA_KEY_INFO_INSTALL : 0),
5570 rsc, NULL, kde, kde_len, gsm->GN, 1);
5571
5572 os_free(kde_buf);
5573 return 0;
5574}
5575
Roshan Pius3a1667e2018-07-03 15:17:14 -07005576
5577int wpa_auth_rekey_gtk(struct wpa_authenticator *wpa_auth)
5578{
5579 if (!wpa_auth)
5580 return -1;
5581 eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL);
5582 return eloop_register_timeout(0, 0, wpa_rekey_gtk, wpa_auth, NULL);
5583}
5584
Hai Shalomb755a2a2020-04-23 21:49:02 -07005585
5586void wpa_auth_set_ft_rsnxe_used(struct wpa_authenticator *wpa_auth, int val)
5587{
5588 if (wpa_auth)
5589 wpa_auth->conf.ft_rsnxe_used = val;
5590}
5591
Hai Shalom899fcc72020-10-19 14:38:18 -07005592
5593void wpa_auth_set_ocv_override_freq(struct wpa_authenticator *wpa_auth,
5594 enum wpa_auth_ocv_override_frame frame,
5595 unsigned int freq)
5596{
5597 if (!wpa_auth)
5598 return;
5599 switch (frame) {
5600 case WPA_AUTH_OCV_OVERRIDE_EAPOL_M3:
5601 wpa_auth->conf.oci_freq_override_eapol_m3 = freq;
5602 break;
5603 case WPA_AUTH_OCV_OVERRIDE_EAPOL_G1:
5604 wpa_auth->conf.oci_freq_override_eapol_g1 = freq;
5605 break;
5606 case WPA_AUTH_OCV_OVERRIDE_FT_ASSOC:
5607 wpa_auth->conf.oci_freq_override_ft_assoc = freq;
5608 break;
5609 case WPA_AUTH_OCV_OVERRIDE_FILS_ASSOC:
5610 wpa_auth->conf.oci_freq_override_fils_assoc = freq;
5611 break;
5612 }
5613}
5614
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005615#endif /* CONFIG_TESTING_OPTIONS */