blob: e48894fdf814b271addf3112f531792134059a14 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002 * IEEE 802.11 RSN / WPA Authenticator
Hai Shalom021b0b52019-04-10 11:17:58 -07003 * Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 */
8
9#include "utils/includes.h"
10
11#include "utils/common.h"
12#include "utils/eloop.h"
13#include "utils/state_machine.h"
Dmitry Shmidtcf32e602014-01-28 10:57:39 -080014#include "utils/bitfield.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070015#include "common/ieee802_11_defs.h"
Hai Shalom74f70d42019-02-11 14:42:39 -080016#include "common/ocv.h"
Hai Shalom4fbc08f2020-05-18 12:37:00 -070017#include "common/dpp.h"
Hai Shalom899fcc72020-10-19 14:38:18 -070018#include "common/wpa_ctrl.h"
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -080019#include "crypto/aes.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070020#include "crypto/aes_wrap.h"
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -080021#include "crypto/aes_siv.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070022#include "crypto/crypto.h"
23#include "crypto/sha1.h"
24#include "crypto/sha256.h"
Roshan Pius3a1667e2018-07-03 15:17:14 -070025#include "crypto/sha384.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070026#include "crypto/random.h"
27#include "eapol_auth/eapol_auth_sm.h"
Hai Shalom74f70d42019-02-11 14:42:39 -080028#include "drivers/driver.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070029#include "ap_config.h"
30#include "ieee802_11.h"
31#include "wpa_auth.h"
32#include "pmksa_cache_auth.h"
33#include "wpa_auth_i.h"
34#include "wpa_auth_ie.h"
35
36#define STATE_MACHINE_DATA struct wpa_state_machine
37#define STATE_MACHINE_DEBUG_PREFIX "WPA"
38#define STATE_MACHINE_ADDR sm->addr
39
40
41static void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx);
42static int wpa_sm_step(struct wpa_state_machine *sm);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070043static int wpa_verify_key_mic(int akmp, size_t pmk_len, struct wpa_ptk *PTK,
44 u8 *data, size_t data_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -080045#ifdef CONFIG_FILS
46static int wpa_aead_decrypt(struct wpa_state_machine *sm, struct wpa_ptk *ptk,
47 u8 *buf, size_t buf_len, u16 *_key_data_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070048static struct wpabuf * fils_prepare_plainbuf(struct wpa_state_machine *sm,
49 const struct wpabuf *hlp);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -080050#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070051static void wpa_sm_call_step(void *eloop_ctx, void *timeout_ctx);
52static void wpa_group_sm_step(struct wpa_authenticator *wpa_auth,
53 struct wpa_group *group);
54static void wpa_request_new_ptk(struct wpa_state_machine *sm);
55static int wpa_gtk_update(struct wpa_authenticator *wpa_auth,
56 struct wpa_group *group);
57static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth,
58 struct wpa_group *group);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080059static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080060 const u8 *pmk, unsigned int pmk_len,
Hai Shalomfdcde762020-04-02 11:19:20 -070061 struct wpa_ptk *ptk, int force_sha256);
Dmitry Shmidt1d755d02015-04-28 10:34:29 -070062static void wpa_group_free(struct wpa_authenticator *wpa_auth,
63 struct wpa_group *group);
64static void wpa_group_get(struct wpa_authenticator *wpa_auth,
65 struct wpa_group *group);
66static void wpa_group_put(struct wpa_authenticator *wpa_auth,
67 struct wpa_group *group);
Hai Shalomfdcde762020-04-02 11:19:20 -070068static int ieee80211w_kde_len(struct wpa_state_machine *sm);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -080069static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070070
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070071static const u32 eapol_key_timeout_first = 100; /* ms */
72static const u32 eapol_key_timeout_subseq = 1000; /* ms */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080073static const u32 eapol_key_timeout_first_group = 500; /* ms */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070074static const u32 eapol_key_timeout_no_retrans = 4000; /* ms */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070075
76/* TODO: make these configurable */
77static const int dot11RSNAConfigPMKLifetime = 43200;
78static const int dot11RSNAConfigPMKReauthThreshold = 70;
79static const int dot11RSNAConfigSATimeout = 60;
80
81
Dmitry Shmidtd5e49232012-12-03 15:08:10 -080082static inline int wpa_auth_mic_failure_report(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070083 struct wpa_authenticator *wpa_auth, const u8 *addr)
84{
Paul Stewart092955c2017-02-06 09:13:09 -080085 if (wpa_auth->cb->mic_failure_report)
86 return wpa_auth->cb->mic_failure_report(wpa_auth->cb_ctx, addr);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -080087 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070088}
89
90
Dmitry Shmidtdda10c22015-03-24 16:05:01 -070091static inline void wpa_auth_psk_failure_report(
92 struct wpa_authenticator *wpa_auth, const u8 *addr)
93{
Paul Stewart092955c2017-02-06 09:13:09 -080094 if (wpa_auth->cb->psk_failure_report)
95 wpa_auth->cb->psk_failure_report(wpa_auth->cb_ctx, addr);
Dmitry Shmidtdda10c22015-03-24 16:05:01 -070096}
97
98
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070099static inline void wpa_auth_set_eapol(struct wpa_authenticator *wpa_auth,
100 const u8 *addr, wpa_eapol_variable var,
101 int value)
102{
Paul Stewart092955c2017-02-06 09:13:09 -0800103 if (wpa_auth->cb->set_eapol)
104 wpa_auth->cb->set_eapol(wpa_auth->cb_ctx, addr, var, value);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700105}
106
107
108static inline int wpa_auth_get_eapol(struct wpa_authenticator *wpa_auth,
109 const u8 *addr, wpa_eapol_variable var)
110{
Hai Shalomfdcde762020-04-02 11:19:20 -0700111 if (!wpa_auth->cb->get_eapol)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700112 return -1;
Paul Stewart092955c2017-02-06 09:13:09 -0800113 return wpa_auth->cb->get_eapol(wpa_auth->cb_ctx, addr, var);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700114}
115
116
117static inline const u8 * wpa_auth_get_psk(struct wpa_authenticator *wpa_auth,
Dmitry Shmidt391c59f2013-09-03 12:16:28 -0700118 const u8 *addr,
119 const u8 *p2p_dev_addr,
Hai Shalom021b0b52019-04-10 11:17:58 -0700120 const u8 *prev_psk, size_t *psk_len,
121 int *vlan_id)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700122{
Hai Shalomfdcde762020-04-02 11:19:20 -0700123 if (!wpa_auth->cb->get_psk)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700124 return NULL;
Paul Stewart092955c2017-02-06 09:13:09 -0800125 return wpa_auth->cb->get_psk(wpa_auth->cb_ctx, addr, p2p_dev_addr,
Hai Shalom021b0b52019-04-10 11:17:58 -0700126 prev_psk, psk_len, vlan_id);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700127}
128
129
130static inline int wpa_auth_get_msk(struct wpa_authenticator *wpa_auth,
131 const u8 *addr, u8 *msk, size_t *len)
132{
Hai Shalomfdcde762020-04-02 11:19:20 -0700133 if (!wpa_auth->cb->get_msk)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700134 return -1;
Paul Stewart092955c2017-02-06 09:13:09 -0800135 return wpa_auth->cb->get_msk(wpa_auth->cb_ctx, addr, msk, len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700136}
137
138
139static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth,
140 int vlan_id,
141 enum wpa_alg alg, const u8 *addr, int idx,
Hai Shalomfdcde762020-04-02 11:19:20 -0700142 u8 *key, size_t key_len,
143 enum key_flag key_flag)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700144{
Hai Shalomfdcde762020-04-02 11:19:20 -0700145 if (!wpa_auth->cb->set_key)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700146 return -1;
Paul Stewart092955c2017-02-06 09:13:09 -0800147 return wpa_auth->cb->set_key(wpa_auth->cb_ctx, vlan_id, alg, addr, idx,
Hai Shalomfdcde762020-04-02 11:19:20 -0700148 key, key_len, key_flag);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700149}
150
151
152static inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth,
153 const u8 *addr, int idx, u8 *seq)
154{
Hai Shalomfdcde762020-04-02 11:19:20 -0700155 int res;
156
157 if (!wpa_auth->cb->get_seqnum)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700158 return -1;
Hai Shalomfdcde762020-04-02 11:19:20 -0700159 res = wpa_auth->cb->get_seqnum(wpa_auth->cb_ctx, addr, idx, seq);
160#ifdef CONFIG_TESTING_OPTIONS
161 if (!addr && idx < 4 && wpa_auth->conf.gtk_rsc_override_set) {
162 wpa_printf(MSG_DEBUG,
163 "TESTING: Override GTK RSC %016llx --> %016llx",
164 (long long unsigned) WPA_GET_LE64(seq),
165 (long long unsigned)
166 WPA_GET_LE64(wpa_auth->conf.gtk_rsc_override));
167 os_memcpy(seq, wpa_auth->conf.gtk_rsc_override,
168 WPA_KEY_RSC_LEN);
169 }
170 if (!addr && idx >= 4 && idx <= 5 &&
171 wpa_auth->conf.igtk_rsc_override_set) {
172 wpa_printf(MSG_DEBUG,
173 "TESTING: Override IGTK RSC %016llx --> %016llx",
174 (long long unsigned) WPA_GET_LE64(seq),
175 (long long unsigned)
176 WPA_GET_LE64(wpa_auth->conf.igtk_rsc_override));
177 os_memcpy(seq, wpa_auth->conf.igtk_rsc_override,
178 WPA_KEY_RSC_LEN);
179 }
180#endif /* CONFIG_TESTING_OPTIONS */
181 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700182}
183
184
185static inline int
186wpa_auth_send_eapol(struct wpa_authenticator *wpa_auth, const u8 *addr,
187 const u8 *data, size_t data_len, int encrypt)
188{
Hai Shalomfdcde762020-04-02 11:19:20 -0700189 if (!wpa_auth->cb->send_eapol)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700190 return -1;
Kai Shie75b0652020-11-24 20:31:29 -0800191#ifdef CONFIG_TESTING_OPTIONS
192 if (wpa_auth->conf.skip_send_eapol)
193 return 0;
194#endif
Paul Stewart092955c2017-02-06 09:13:09 -0800195 return wpa_auth->cb->send_eapol(wpa_auth->cb_ctx, addr, data, data_len,
196 encrypt);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700197}
198
199
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800200#ifdef CONFIG_MESH
201static inline int wpa_auth_start_ampe(struct wpa_authenticator *wpa_auth,
202 const u8 *addr)
203{
Hai Shalomfdcde762020-04-02 11:19:20 -0700204 if (!wpa_auth->cb->start_ampe)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800205 return -1;
Paul Stewart092955c2017-02-06 09:13:09 -0800206 return wpa_auth->cb->start_ampe(wpa_auth->cb_ctx, addr);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800207}
208#endif /* CONFIG_MESH */
209
210
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700211int wpa_auth_for_each_sta(struct wpa_authenticator *wpa_auth,
212 int (*cb)(struct wpa_state_machine *sm, void *ctx),
213 void *cb_ctx)
214{
Hai Shalomfdcde762020-04-02 11:19:20 -0700215 if (!wpa_auth->cb->for_each_sta)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700216 return 0;
Paul Stewart092955c2017-02-06 09:13:09 -0800217 return wpa_auth->cb->for_each_sta(wpa_auth->cb_ctx, cb, cb_ctx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700218}
219
220
221int wpa_auth_for_each_auth(struct wpa_authenticator *wpa_auth,
222 int (*cb)(struct wpa_authenticator *a, void *ctx),
223 void *cb_ctx)
224{
Hai Shalomfdcde762020-04-02 11:19:20 -0700225 if (!wpa_auth->cb->for_each_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700226 return 0;
Paul Stewart092955c2017-02-06 09:13:09 -0800227 return wpa_auth->cb->for_each_auth(wpa_auth->cb_ctx, cb, cb_ctx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700228}
229
230
231void wpa_auth_logger(struct wpa_authenticator *wpa_auth, const u8 *addr,
232 logger_level level, const char *txt)
233{
Hai Shalomfdcde762020-04-02 11:19:20 -0700234 if (!wpa_auth->cb->logger)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700235 return;
Paul Stewart092955c2017-02-06 09:13:09 -0800236 wpa_auth->cb->logger(wpa_auth->cb_ctx, addr, level, txt);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700237}
238
239
240void wpa_auth_vlogger(struct wpa_authenticator *wpa_auth, const u8 *addr,
241 logger_level level, const char *fmt, ...)
242{
243 char *format;
244 int maxlen;
245 va_list ap;
246
Hai Shalomfdcde762020-04-02 11:19:20 -0700247 if (!wpa_auth->cb->logger)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700248 return;
249
250 maxlen = os_strlen(fmt) + 100;
251 format = os_malloc(maxlen);
252 if (!format)
253 return;
254
255 va_start(ap, fmt);
256 vsnprintf(format, maxlen, fmt, ap);
257 va_end(ap);
258
259 wpa_auth_logger(wpa_auth, addr, level, format);
260
261 os_free(format);
262}
263
264
265static void wpa_sta_disconnect(struct wpa_authenticator *wpa_auth,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700266 const u8 *addr, u16 reason)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700267{
Hai Shalomfdcde762020-04-02 11:19:20 -0700268 if (!wpa_auth->cb->disconnect)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700269 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700270 wpa_printf(MSG_DEBUG, "wpa_sta_disconnect STA " MACSTR " (reason %u)",
271 MAC2STR(addr), reason);
272 wpa_auth->cb->disconnect(wpa_auth->cb_ctx, addr, reason);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700273}
274
275
Hai Shalom74f70d42019-02-11 14:42:39 -0800276#ifdef CONFIG_OCV
277static int wpa_channel_info(struct wpa_authenticator *wpa_auth,
278 struct wpa_channel_info *ci)
279{
280 if (!wpa_auth->cb->channel_info)
281 return -1;
282 return wpa_auth->cb->channel_info(wpa_auth->cb_ctx, ci);
283}
284#endif /* CONFIG_OCV */
285
286
Hai Shalom021b0b52019-04-10 11:17:58 -0700287static int wpa_auth_update_vlan(struct wpa_authenticator *wpa_auth,
288 const u8 *addr, int vlan_id)
289{
290 if (!wpa_auth->cb->update_vlan)
291 return -1;
292 return wpa_auth->cb->update_vlan(wpa_auth->cb_ctx, addr, vlan_id);
293}
294
295
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700296static void wpa_rekey_gmk(void *eloop_ctx, void *timeout_ctx)
297{
298 struct wpa_authenticator *wpa_auth = eloop_ctx;
299
300 if (random_get_bytes(wpa_auth->group->GMK, WPA_GMK_LEN)) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700301 wpa_printf(MSG_ERROR,
302 "Failed to get random data for WPA initialization.");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700303 } else {
304 wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "GMK rekeyd");
305 wpa_hexdump_key(MSG_DEBUG, "GMK",
306 wpa_auth->group->GMK, WPA_GMK_LEN);
307 }
308
309 if (wpa_auth->conf.wpa_gmk_rekey) {
310 eloop_register_timeout(wpa_auth->conf.wpa_gmk_rekey, 0,
311 wpa_rekey_gmk, wpa_auth, NULL);
312 }
313}
314
315
316static void wpa_rekey_gtk(void *eloop_ctx, void *timeout_ctx)
317{
318 struct wpa_authenticator *wpa_auth = eloop_ctx;
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700319 struct wpa_group *group, *next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700320
321 wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "rekeying GTK");
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700322 group = wpa_auth->group;
323 while (group) {
324 wpa_group_get(wpa_auth, group);
325
Hai Shalome21d4e82020-04-29 16:34:06 -0700326 group->GTKReKey = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700327 do {
Hai Shalome21d4e82020-04-29 16:34:06 -0700328 group->changed = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700329 wpa_group_sm_step(wpa_auth, group);
330 } while (group->changed);
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700331
332 next = group->next;
333 wpa_group_put(wpa_auth, group);
334 group = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700335 }
336
337 if (wpa_auth->conf.wpa_group_rekey) {
338 eloop_register_timeout(wpa_auth->conf.wpa_group_rekey,
339 0, wpa_rekey_gtk, wpa_auth, NULL);
340 }
341}
342
343
344static void wpa_rekey_ptk(void *eloop_ctx, void *timeout_ctx)
345{
346 struct wpa_authenticator *wpa_auth = eloop_ctx;
347 struct wpa_state_machine *sm = timeout_ctx;
348
349 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "rekeying PTK");
350 wpa_request_new_ptk(sm);
351 wpa_sm_step(sm);
352}
353
354
Hai Shalom81f62d82019-07-22 12:10:00 -0700355void wpa_auth_set_ptk_rekey_timer(struct wpa_state_machine *sm)
356{
357 if (sm && sm->wpa_auth->conf.wpa_ptk_rekey) {
358 wpa_printf(MSG_DEBUG, "WPA: Start PTK rekeying timer for "
359 MACSTR " (%d seconds)", MAC2STR(sm->addr),
360 sm->wpa_auth->conf.wpa_ptk_rekey);
361 eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm);
362 eloop_register_timeout(sm->wpa_auth->conf.wpa_ptk_rekey, 0,
363 wpa_rekey_ptk, sm->wpa_auth, sm);
364 }
365}
366
367
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700368static int wpa_auth_pmksa_clear_cb(struct wpa_state_machine *sm, void *ctx)
369{
370 if (sm->pmksa == ctx)
371 sm->pmksa = NULL;
372 return 0;
373}
374
375
376static void wpa_auth_pmksa_free_cb(struct rsn_pmksa_cache_entry *entry,
377 void *ctx)
378{
379 struct wpa_authenticator *wpa_auth = ctx;
380 wpa_auth_for_each_sta(wpa_auth, wpa_auth_pmksa_clear_cb, entry);
381}
382
383
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700384static int wpa_group_init_gmk_and_counter(struct wpa_authenticator *wpa_auth,
385 struct wpa_group *group)
386{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800387 u8 buf[ETH_ALEN + 8 + sizeof(unsigned long)];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700388 u8 rkey[32];
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800389 unsigned long ptr;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700390
391 if (random_get_bytes(group->GMK, WPA_GMK_LEN) < 0)
392 return -1;
393 wpa_hexdump_key(MSG_DEBUG, "GMK", group->GMK, WPA_GMK_LEN);
394
395 /*
396 * Counter = PRF-256(Random number, "Init Counter",
397 * Local MAC Address || Time)
398 */
399 os_memcpy(buf, wpa_auth->addr, ETH_ALEN);
400 wpa_get_ntp_timestamp(buf + ETH_ALEN);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800401 ptr = (unsigned long) group;
402 os_memcpy(buf + ETH_ALEN + 8, &ptr, sizeof(ptr));
Hai Shalom74f70d42019-02-11 14:42:39 -0800403#ifdef TEST_FUZZ
404 os_memset(buf + ETH_ALEN, 0xab, 8);
405 os_memset(buf + ETH_ALEN + 8, 0xcd, sizeof(ptr));
406#endif /* TEST_FUZZ */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700407 if (random_get_bytes(rkey, sizeof(rkey)) < 0)
408 return -1;
409
410 if (sha1_prf(rkey, sizeof(rkey), "Init Counter", buf, sizeof(buf),
411 group->Counter, WPA_NONCE_LEN) < 0)
412 return -1;
413 wpa_hexdump_key(MSG_DEBUG, "Key Counter",
414 group->Counter, WPA_NONCE_LEN);
415
416 return 0;
417}
418
419
420static struct wpa_group * wpa_group_init(struct wpa_authenticator *wpa_auth,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800421 int vlan_id, int delay_init)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700422{
423 struct wpa_group *group;
424
425 group = os_zalloc(sizeof(struct wpa_group));
Hai Shalomfdcde762020-04-02 11:19:20 -0700426 if (!group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700427 return NULL;
428
Hai Shalome21d4e82020-04-29 16:34:06 -0700429 group->GTKAuthenticator = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700430 group->vlan_id = vlan_id;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -0700431 group->GTK_len = wpa_cipher_key_len(wpa_auth->conf.wpa_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700432
433 if (random_pool_ready() != 1) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700434 wpa_printf(MSG_INFO,
435 "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 -0700436 }
437
438 /*
439 * Set initial GMK/Counter value here. The actual values that will be
440 * used in negotiations will be set once the first station tries to
441 * connect. This allows more time for collecting additional randomness
442 * on embedded devices.
443 */
444 if (wpa_group_init_gmk_and_counter(wpa_auth, group) < 0) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700445 wpa_printf(MSG_ERROR,
446 "Failed to get random data for WPA initialization.");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700447 os_free(group);
448 return NULL;
449 }
450
Hai Shalome21d4e82020-04-29 16:34:06 -0700451 group->GInit = true;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800452 if (delay_init) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700453 wpa_printf(MSG_DEBUG,
454 "WPA: Delay group state machine start until Beacon frames have been configured");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800455 /* Initialization is completed in wpa_init_keys(). */
456 } else {
457 wpa_group_sm_step(wpa_auth, group);
Hai Shalome21d4e82020-04-29 16:34:06 -0700458 group->GInit = false;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800459 wpa_group_sm_step(wpa_auth, group);
460 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700461
462 return group;
463}
464
465
466/**
467 * wpa_init - Initialize WPA authenticator
468 * @addr: Authenticator address
469 * @conf: Configuration for WPA authenticator
470 * @cb: Callback functions for WPA authenticator
471 * Returns: Pointer to WPA authenticator data or %NULL on failure
472 */
473struct wpa_authenticator * wpa_init(const u8 *addr,
474 struct wpa_auth_config *conf,
Paul Stewart092955c2017-02-06 09:13:09 -0800475 const struct wpa_auth_callbacks *cb,
476 void *cb_ctx)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700477{
478 struct wpa_authenticator *wpa_auth;
479
480 wpa_auth = os_zalloc(sizeof(struct wpa_authenticator));
Hai Shalomfdcde762020-04-02 11:19:20 -0700481 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700482 return NULL;
483 os_memcpy(wpa_auth->addr, addr, ETH_ALEN);
484 os_memcpy(&wpa_auth->conf, conf, sizeof(*conf));
Paul Stewart092955c2017-02-06 09:13:09 -0800485 wpa_auth->cb = cb;
486 wpa_auth->cb_ctx = cb_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700487
488 if (wpa_auth_gen_wpa_ie(wpa_auth)) {
489 wpa_printf(MSG_ERROR, "Could not generate WPA IE.");
490 os_free(wpa_auth);
491 return NULL;
492 }
493
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800494 wpa_auth->group = wpa_group_init(wpa_auth, 0, 1);
Hai Shalomfdcde762020-04-02 11:19:20 -0700495 if (!wpa_auth->group) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700496 os_free(wpa_auth->wpa_ie);
497 os_free(wpa_auth);
498 return NULL;
499 }
500
501 wpa_auth->pmksa = pmksa_cache_auth_init(wpa_auth_pmksa_free_cb,
502 wpa_auth);
Hai Shalomfdcde762020-04-02 11:19:20 -0700503 if (!wpa_auth->pmksa) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700504 wpa_printf(MSG_ERROR, "PMKSA cache initialization failed.");
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800505 os_free(wpa_auth->group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700506 os_free(wpa_auth->wpa_ie);
507 os_free(wpa_auth);
508 return NULL;
509 }
510
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800511#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700512 wpa_auth->ft_pmk_cache = wpa_ft_pmk_cache_init();
Hai Shalomfdcde762020-04-02 11:19:20 -0700513 if (!wpa_auth->ft_pmk_cache) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700514 wpa_printf(MSG_ERROR, "FT PMK cache initialization failed.");
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800515 os_free(wpa_auth->group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700516 os_free(wpa_auth->wpa_ie);
517 pmksa_cache_auth_deinit(wpa_auth->pmksa);
518 os_free(wpa_auth);
519 return NULL;
520 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800521#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700522
523 if (wpa_auth->conf.wpa_gmk_rekey) {
524 eloop_register_timeout(wpa_auth->conf.wpa_gmk_rekey, 0,
525 wpa_rekey_gmk, wpa_auth, NULL);
526 }
527
528 if (wpa_auth->conf.wpa_group_rekey) {
529 eloop_register_timeout(wpa_auth->conf.wpa_group_rekey, 0,
530 wpa_rekey_gtk, wpa_auth, NULL);
531 }
532
Dmitry Shmidtcf32e602014-01-28 10:57:39 -0800533#ifdef CONFIG_P2P
534 if (WPA_GET_BE32(conf->ip_addr_start)) {
535 int count = WPA_GET_BE32(conf->ip_addr_end) -
536 WPA_GET_BE32(conf->ip_addr_start) + 1;
537 if (count > 1000)
538 count = 1000;
539 if (count > 0)
540 wpa_auth->ip_pool = bitfield_alloc(count);
541 }
542#endif /* CONFIG_P2P */
543
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700544 return wpa_auth;
545}
546
547
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800548int wpa_init_keys(struct wpa_authenticator *wpa_auth)
549{
550 struct wpa_group *group = wpa_auth->group;
551
Hai Shalomfdcde762020-04-02 11:19:20 -0700552 wpa_printf(MSG_DEBUG,
553 "WPA: Start group state machine to set initial keys");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800554 wpa_group_sm_step(wpa_auth, group);
Hai Shalome21d4e82020-04-29 16:34:06 -0700555 group->GInit = false;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800556 wpa_group_sm_step(wpa_auth, group);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800557 if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
558 return -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800559 return 0;
560}
561
562
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700563/**
564 * wpa_deinit - Deinitialize WPA authenticator
565 * @wpa_auth: Pointer to WPA authenticator data from wpa_init()
566 */
567void wpa_deinit(struct wpa_authenticator *wpa_auth)
568{
569 struct wpa_group *group, *prev;
570
571 eloop_cancel_timeout(wpa_rekey_gmk, wpa_auth, NULL);
572 eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL);
573
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700574 pmksa_cache_auth_deinit(wpa_auth->pmksa);
575
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800576#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700577 wpa_ft_pmk_cache_deinit(wpa_auth->ft_pmk_cache);
578 wpa_auth->ft_pmk_cache = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700579 wpa_ft_deinit(wpa_auth);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800580#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700581
Dmitry Shmidtcf32e602014-01-28 10:57:39 -0800582#ifdef CONFIG_P2P
583 bitfield_free(wpa_auth->ip_pool);
584#endif /* CONFIG_P2P */
585
586
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700587 os_free(wpa_auth->wpa_ie);
588
589 group = wpa_auth->group;
590 while (group) {
591 prev = group;
592 group = group->next;
593 os_free(prev);
594 }
595
596 os_free(wpa_auth);
597}
598
599
600/**
601 * wpa_reconfig - Update WPA authenticator configuration
602 * @wpa_auth: Pointer to WPA authenticator data from wpa_init()
603 * @conf: Configuration for WPA authenticator
604 */
605int wpa_reconfig(struct wpa_authenticator *wpa_auth,
606 struct wpa_auth_config *conf)
607{
608 struct wpa_group *group;
Hai Shalomfdcde762020-04-02 11:19:20 -0700609
610 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700611 return 0;
612
613 os_memcpy(&wpa_auth->conf, conf, sizeof(*conf));
614 if (wpa_auth_gen_wpa_ie(wpa_auth)) {
615 wpa_printf(MSG_ERROR, "Could not generate WPA IE.");
616 return -1;
617 }
618
619 /*
620 * Reinitialize GTK to make sure it is suitable for the new
621 * configuration.
622 */
623 group = wpa_auth->group;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -0700624 group->GTK_len = wpa_cipher_key_len(wpa_auth->conf.wpa_group);
Hai Shalome21d4e82020-04-29 16:34:06 -0700625 group->GInit = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700626 wpa_group_sm_step(wpa_auth, group);
Hai Shalome21d4e82020-04-29 16:34:06 -0700627 group->GInit = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700628 wpa_group_sm_step(wpa_auth, group);
629
630 return 0;
631}
632
633
634struct wpa_state_machine *
Dmitry Shmidt391c59f2013-09-03 12:16:28 -0700635wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr,
636 const u8 *p2p_dev_addr)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700637{
638 struct wpa_state_machine *sm;
639
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800640 if (wpa_auth->group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
641 return NULL;
642
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700643 sm = os_zalloc(sizeof(struct wpa_state_machine));
Hai Shalomfdcde762020-04-02 11:19:20 -0700644 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700645 return NULL;
646 os_memcpy(sm->addr, addr, ETH_ALEN);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -0700647 if (p2p_dev_addr)
648 os_memcpy(sm->p2p_dev_addr, p2p_dev_addr, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700649
650 sm->wpa_auth = wpa_auth;
651 sm->group = wpa_auth->group;
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700652 wpa_group_get(sm->wpa_auth, sm->group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700653
654 return sm;
655}
656
657
658int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth,
659 struct wpa_state_machine *sm)
660{
Hai Shalomfdcde762020-04-02 11:19:20 -0700661 if (!wpa_auth || !wpa_auth->conf.wpa || !sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700662 return -1;
663
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800664#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700665 if (sm->ft_completed) {
666 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -0700667 "FT authentication already completed - do not start 4-way handshake");
Dmitry Shmidt71757432014-06-02 13:50:35 -0700668 /* Go to PTKINITDONE state to allow GTK rekeying */
669 sm->wpa_ptk_state = WPA_PTK_PTKINITDONE;
Hai Shalome21d4e82020-04-29 16:34:06 -0700670 sm->Pair = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700671 return 0;
672 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800673#endif /* CONFIG_IEEE80211R_AP */
674
675#ifdef CONFIG_FILS
676 if (sm->fils_completed) {
677 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
678 "FILS authentication already completed - do not start 4-way handshake");
679 /* Go to PTKINITDONE state to allow GTK rekeying */
680 sm->wpa_ptk_state = WPA_PTK_PTKINITDONE;
Hai Shalome21d4e82020-04-29 16:34:06 -0700681 sm->Pair = true;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800682 return 0;
683 }
684#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700685
686 if (sm->started) {
687 os_memset(&sm->key_replay, 0, sizeof(sm->key_replay));
Hai Shalome21d4e82020-04-29 16:34:06 -0700688 sm->ReAuthenticationRequest = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700689 return wpa_sm_step(sm);
690 }
691
692 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
693 "start authentication");
694 sm->started = 1;
695
Hai Shalome21d4e82020-04-29 16:34:06 -0700696 sm->Init = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700697 if (wpa_sm_step(sm) == 1)
698 return 1; /* should not really happen */
Hai Shalome21d4e82020-04-29 16:34:06 -0700699 sm->Init = false;
700 sm->AuthenticationRequest = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700701 return wpa_sm_step(sm);
702}
703
704
705void wpa_auth_sta_no_wpa(struct wpa_state_machine *sm)
706{
707 /* WPA/RSN was not used - clear WPA state. This is needed if the STA
708 * reassociates back to the same AP while the previous entry for the
709 * STA has not yet been removed. */
Hai Shalomfdcde762020-04-02 11:19:20 -0700710 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700711 return;
712
713 sm->wpa_key_mgmt = 0;
714}
715
716
717static void wpa_free_sta_sm(struct wpa_state_machine *sm)
718{
Dmitry Shmidtcf32e602014-01-28 10:57:39 -0800719#ifdef CONFIG_P2P
720 if (WPA_GET_BE32(sm->ip_addr)) {
721 u32 start;
Hai Shalomfdcde762020-04-02 11:19:20 -0700722 wpa_printf(MSG_DEBUG,
723 "P2P: Free assigned IP address %u.%u.%u.%u from "
724 MACSTR,
Dmitry Shmidtcf32e602014-01-28 10:57:39 -0800725 sm->ip_addr[0], sm->ip_addr[1],
726 sm->ip_addr[2], sm->ip_addr[3],
727 MAC2STR(sm->addr));
728 start = WPA_GET_BE32(sm->wpa_auth->conf.ip_addr_start);
729 bitfield_clear(sm->wpa_auth->ip_pool,
730 WPA_GET_BE32(sm->ip_addr) - start);
731 }
732#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700733 if (sm->GUpdateStationKeys) {
734 sm->group->GKeyDoneStations--;
Hai Shalome21d4e82020-04-29 16:34:06 -0700735 sm->GUpdateStationKeys = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700736 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800737#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700738 os_free(sm->assoc_resp_ftie);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700739 wpabuf_free(sm->ft_pending_req_ies);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800740#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700741 os_free(sm->last_rx_eapol_key);
742 os_free(sm->wpa_ie);
Hai Shalomc3565922019-10-28 11:58:20 -0700743 os_free(sm->rsnxe);
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700744 wpa_group_put(sm->wpa_auth, sm->group);
Hai Shalom021b0b52019-04-10 11:17:58 -0700745#ifdef CONFIG_DPP2
746 wpabuf_clear_free(sm->dpp_z);
747#endif /* CONFIG_DPP2 */
Hai Shalom1dc4d202019-04-29 16:22:27 -0700748 bin_clear_free(sm, sizeof(*sm));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700749}
750
751
752void wpa_auth_sta_deinit(struct wpa_state_machine *sm)
753{
Hai Shalomfdcde762020-04-02 11:19:20 -0700754 struct wpa_authenticator *wpa_auth;
755
756 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700757 return;
758
Hai Shalomfdcde762020-04-02 11:19:20 -0700759 wpa_auth = sm->wpa_auth;
760 if (wpa_auth->conf.wpa_strict_rekey && sm->has_GTK) {
761 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
762 "strict rekeying - force GTK rekey since STA is leaving");
Roshan Pius3a1667e2018-07-03 15:17:14 -0700763 if (eloop_deplete_timeout(0, 500000, wpa_rekey_gtk,
Hai Shalomfdcde762020-04-02 11:19:20 -0700764 wpa_auth, NULL) == -1)
765 eloop_register_timeout(0, 500000, wpa_rekey_gtk,
766 wpa_auth, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700767 }
768
Hai Shalomfdcde762020-04-02 11:19:20 -0700769 eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700770 sm->pending_1_of_4_timeout = 0;
771 eloop_cancel_timeout(wpa_sm_call_step, sm, NULL);
Hai Shalomfdcde762020-04-02 11:19:20 -0700772 eloop_cancel_timeout(wpa_rekey_ptk, wpa_auth, sm);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700773#ifdef CONFIG_IEEE80211R_AP
774 wpa_ft_sta_deinit(sm);
775#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700776 if (sm->in_step_loop) {
777 /* Must not free state machine while wpa_sm_step() is running.
778 * Freeing will be completed in the end of wpa_sm_step(). */
Hai Shalomfdcde762020-04-02 11:19:20 -0700779 wpa_printf(MSG_DEBUG,
780 "WPA: Registering pending STA state machine deinit for "
781 MACSTR, MAC2STR(sm->addr));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700782 sm->pending_deinit = 1;
783 } else
784 wpa_free_sta_sm(sm);
785}
786
787
788static void wpa_request_new_ptk(struct wpa_state_machine *sm)
789{
Hai Shalomfdcde762020-04-02 11:19:20 -0700790 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700791 return;
792
Hai Shalomfdcde762020-04-02 11:19:20 -0700793 if (!sm->use_ext_key_id && sm->wpa_auth->conf.wpa_deny_ptk0_rekey) {
794 wpa_printf(MSG_INFO,
795 "WPA: PTK0 rekey not allowed, disconnect " MACSTR,
796 MAC2STR(sm->addr));
Hai Shalome21d4e82020-04-29 16:34:06 -0700797 sm->Disconnect = true;
Hai Shalomfdcde762020-04-02 11:19:20 -0700798 /* Try to encourage the STA to reconnect */
799 sm->disconnect_reason =
800 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA;
801 } else {
802 if (sm->use_ext_key_id)
803 sm->keyidx_active ^= 1; /* flip Key ID */
Hai Shalome21d4e82020-04-29 16:34:06 -0700804 sm->PTKRequest = true;
Hai Shalomfdcde762020-04-02 11:19:20 -0700805 sm->PTK_valid = 0;
806 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700807}
808
809
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800810static int wpa_replay_counter_valid(struct wpa_key_replay_counter *ctr,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700811 const u8 *replay_counter)
812{
813 int i;
814 for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800815 if (!ctr[i].valid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700816 break;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800817 if (os_memcmp(replay_counter, ctr[i].counter,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700818 WPA_REPLAY_COUNTER_LEN) == 0)
819 return 1;
820 }
821 return 0;
822}
823
824
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800825static void wpa_replay_counter_mark_invalid(struct wpa_key_replay_counter *ctr,
826 const u8 *replay_counter)
827{
828 int i;
829 for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) {
830 if (ctr[i].valid &&
Hai Shalomfdcde762020-04-02 11:19:20 -0700831 (!replay_counter ||
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800832 os_memcmp(replay_counter, ctr[i].counter,
833 WPA_REPLAY_COUNTER_LEN) == 0))
Hai Shalome21d4e82020-04-29 16:34:06 -0700834 ctr[i].valid = false;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800835 }
836}
837
838
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800839#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700840static int ft_check_msg_2_of_4(struct wpa_authenticator *wpa_auth,
841 struct wpa_state_machine *sm,
842 struct wpa_eapol_ie_parse *kde)
843{
844 struct wpa_ie_data ie;
845 struct rsn_mdie *mdie;
846
847 if (wpa_parse_wpa_ie_rsn(kde->rsn_ie, kde->rsn_ie_len, &ie) < 0 ||
Hai Shalomfdcde762020-04-02 11:19:20 -0700848 ie.num_pmkid != 1 || !ie.pmkid) {
849 wpa_printf(MSG_DEBUG,
850 "FT: No PMKR1Name in FT 4-way handshake message 2/4");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700851 return -1;
852 }
853
854 os_memcpy(sm->sup_pmk_r1_name, ie.pmkid, PMKID_LEN);
855 wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from Supplicant",
856 sm->sup_pmk_r1_name, PMKID_LEN);
857
858 if (!kde->mdie || !kde->ftie) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700859 wpa_printf(MSG_DEBUG,
860 "FT: No %s in FT 4-way handshake message 2/4",
861 kde->mdie ? "FTIE" : "MDIE");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700862 return -1;
863 }
864
865 mdie = (struct rsn_mdie *) (kde->mdie + 2);
866 if (kde->mdie[1] < sizeof(struct rsn_mdie) ||
867 os_memcmp(wpa_auth->conf.mobility_domain, mdie->mobility_domain,
868 MOBILITY_DOMAIN_ID_LEN) != 0) {
869 wpa_printf(MSG_DEBUG, "FT: MDIE mismatch");
870 return -1;
871 }
872
873 if (sm->assoc_resp_ftie &&
874 (kde->ftie[1] != sm->assoc_resp_ftie[1] ||
875 os_memcmp(kde->ftie, sm->assoc_resp_ftie,
876 2 + sm->assoc_resp_ftie[1]) != 0)) {
877 wpa_printf(MSG_DEBUG, "FT: FTIE mismatch");
878 wpa_hexdump(MSG_DEBUG, "FT: FTIE in EAPOL-Key msg 2/4",
879 kde->ftie, kde->ftie_len);
880 wpa_hexdump(MSG_DEBUG, "FT: FTIE in (Re)AssocResp",
881 sm->assoc_resp_ftie, 2 + sm->assoc_resp_ftie[1]);
882 return -1;
883 }
884
885 return 0;
886}
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800887#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700888
889
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800890static int wpa_receive_error_report(struct wpa_authenticator *wpa_auth,
891 struct wpa_state_machine *sm, int group)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800892{
893 /* Supplicant reported a Michael MIC error */
894 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -0700895 "received EAPOL-Key Error Request (STA detected Michael MIC failure (group=%d))",
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800896 group);
897
898 if (group && wpa_auth->conf.wpa_group != WPA_CIPHER_TKIP) {
899 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -0700900 "ignore Michael MIC failure report since group cipher is not TKIP");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800901 } else if (!group && sm->pairwise != WPA_CIPHER_TKIP) {
902 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -0700903 "ignore Michael MIC failure report since pairwise cipher is not TKIP");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800904 } else {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800905 if (wpa_auth_mic_failure_report(wpa_auth, sm->addr) > 0)
906 return 1; /* STA entry was removed */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800907 sm->dot11RSNAStatsTKIPRemoteMICFailures++;
908 wpa_auth->dot11RSNAStatsTKIPRemoteMICFailures++;
909 }
910
911 /*
912 * Error report is not a request for a new key handshake, but since
913 * Authenticator may do it, let's change the keys now anyway.
914 */
915 wpa_request_new_ptk(sm);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800916 return 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800917}
918
919
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800920static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data,
921 size_t data_len)
922{
923 struct wpa_ptk PTK;
924 int ok = 0;
925 const u8 *pmk = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700926 size_t pmk_len;
Hai Shalom021b0b52019-04-10 11:17:58 -0700927 int vlan_id = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800928
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800929 os_memset(&PTK, 0, sizeof(PTK));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800930 for (;;) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700931 if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
932 !wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800933 pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr,
Hai Shalom021b0b52019-04-10 11:17:58 -0700934 sm->p2p_dev_addr, pmk, &pmk_len,
935 &vlan_id);
Hai Shalomfdcde762020-04-02 11:19:20 -0700936 if (!pmk)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800937 break;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700938#ifdef CONFIG_IEEE80211R_AP
939 if (wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) {
940 os_memcpy(sm->xxkey, pmk, pmk_len);
941 sm->xxkey_len = pmk_len;
942 }
943#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800944 } else {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800945 pmk = sm->PMK;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800946 pmk_len = sm->pmk_len;
947 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800948
Hai Shalomfdcde762020-04-02 11:19:20 -0700949 if (wpa_derive_ptk(sm, sm->alt_SNonce, pmk, pmk_len, &PTK, 0) <
950 0)
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800951 break;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800952
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700953 if (wpa_verify_key_mic(sm->wpa_key_mgmt, pmk_len, &PTK,
954 data, data_len) == 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -0700955 if (sm->PMK != pmk) {
956 os_memcpy(sm->PMK, pmk, pmk_len);
957 sm->pmk_len = pmk_len;
958 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800959 ok = 1;
960 break;
961 }
962
Roshan Pius3a1667e2018-07-03 15:17:14 -0700963 if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
964 wpa_key_mgmt_sae(sm->wpa_key_mgmt))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800965 break;
966 }
967
968 if (!ok) {
969 wpa_printf(MSG_DEBUG,
970 "WPA: Earlier SNonce did not result in matching MIC");
971 return -1;
972 }
973
974 wpa_printf(MSG_DEBUG,
975 "WPA: Earlier SNonce resulted in matching MIC");
976 sm->alt_snonce_valid = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -0700977
978 if (vlan_id && wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
979 wpa_auth_update_vlan(sm->wpa_auth, sm->addr, vlan_id) < 0)
980 return -1;
981
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800982 os_memcpy(sm->SNonce, sm->alt_SNonce, WPA_NONCE_LEN);
983 os_memcpy(&sm->PTK, &PTK, sizeof(PTK));
Hai Shalom81f62d82019-07-22 12:10:00 -0700984 forced_memzero(&PTK, sizeof(PTK));
Hai Shalome21d4e82020-04-29 16:34:06 -0700985 sm->PTK_valid = true;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800986
987 return 0;
988}
989
990
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700991void wpa_receive(struct wpa_authenticator *wpa_auth,
992 struct wpa_state_machine *sm,
993 u8 *data, size_t data_len)
994{
995 struct ieee802_1x_hdr *hdr;
996 struct wpa_eapol_key *key;
997 u16 key_info, key_data_length;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700998 enum { PAIRWISE_2, PAIRWISE_4, GROUP_2, REQUEST } msg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700999 char *msgtxt;
1000 struct wpa_eapol_ie_parse kde;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001001 const u8 *key_data;
1002 size_t keyhdrlen, mic_len;
1003 u8 *mic;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001004
Hai Shalomfdcde762020-04-02 11:19:20 -07001005 if (!wpa_auth || !wpa_auth->conf.wpa || !sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001006 return;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001007 wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL data", data, data_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001008
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001009 mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001010 keyhdrlen = sizeof(*key) + mic_len + 2;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001011
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001012 if (data_len < sizeof(*hdr) + keyhdrlen) {
1013 wpa_printf(MSG_DEBUG, "WPA: Ignore too short EAPOL-Key frame");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001014 return;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001015 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001016
1017 hdr = (struct ieee802_1x_hdr *) data;
1018 key = (struct wpa_eapol_key *) (hdr + 1);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001019 mic = (u8 *) (key + 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001020 key_info = WPA_GET_BE16(key->key_info);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001021 key_data = mic + mic_len + 2;
1022 key_data_length = WPA_GET_BE16(mic + mic_len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001023 wpa_printf(MSG_DEBUG, "WPA: Received EAPOL-Key from " MACSTR
Hai Shalomfdcde762020-04-02 11:19:20 -07001024 " key_info=0x%x type=%u mic_len=%zu key_data_length=%u",
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001025 MAC2STR(sm->addr), key_info, key->type,
Hai Shalomfdcde762020-04-02 11:19:20 -07001026 mic_len, key_data_length);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001027 wpa_hexdump(MSG_MSGDUMP,
1028 "WPA: EAPOL-Key header (ending before Key MIC)",
1029 key, sizeof(*key));
1030 wpa_hexdump(MSG_MSGDUMP, "WPA: EAPOL-Key Key MIC",
1031 mic, mic_len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001032 if (key_data_length > data_len - sizeof(*hdr) - keyhdrlen) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001033 wpa_printf(MSG_INFO,
1034 "WPA: Invalid EAPOL-Key frame - key_data overflow (%d > %zu)",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001035 key_data_length,
Hai Shalomfdcde762020-04-02 11:19:20 -07001036 data_len - sizeof(*hdr) - keyhdrlen);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001037 return;
1038 }
1039
1040 if (sm->wpa == WPA_VERSION_WPA2) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001041 if (key->type == EAPOL_KEY_TYPE_WPA) {
1042 /*
1043 * Some deployed station implementations seem to send
1044 * msg 4/4 with incorrect type value in WPA2 mode.
1045 */
Hai Shalomfdcde762020-04-02 11:19:20 -07001046 wpa_printf(MSG_DEBUG,
1047 "Workaround: Allow EAPOL-Key with unexpected WPA type in RSN mode");
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001048 } else if (key->type != EAPOL_KEY_TYPE_RSN) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001049 wpa_printf(MSG_DEBUG,
1050 "Ignore EAPOL-Key with unexpected type %d in RSN mode",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001051 key->type);
1052 return;
1053 }
1054 } else {
1055 if (key->type != EAPOL_KEY_TYPE_WPA) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001056 wpa_printf(MSG_DEBUG,
1057 "Ignore EAPOL-Key with unexpected type %d in WPA mode",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001058 key->type);
1059 return;
1060 }
1061 }
1062
1063 wpa_hexdump(MSG_DEBUG, "WPA: Received Key Nonce", key->key_nonce,
1064 WPA_NONCE_LEN);
1065 wpa_hexdump(MSG_DEBUG, "WPA: Received Replay Counter",
1066 key->replay_counter, WPA_REPLAY_COUNTER_LEN);
1067
1068 /* FIX: verify that the EAPOL-Key frame was encrypted if pairwise keys
1069 * are set */
1070
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001071 if (key_info & WPA_KEY_INFO_SMK_MESSAGE) {
1072 wpa_printf(MSG_DEBUG, "WPA: Ignore SMK message");
1073 return;
1074 }
1075
1076 if (key_info & WPA_KEY_INFO_REQUEST) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001077 msg = REQUEST;
1078 msgtxt = "Request";
1079 } else if (!(key_info & WPA_KEY_INFO_KEY_TYPE)) {
1080 msg = GROUP_2;
1081 msgtxt = "2/2 Group";
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001082 } else if (key_data_length == 0 ||
1083 (mic_len == 0 && (key_info & WPA_KEY_INFO_ENCR_KEY_DATA) &&
1084 key_data_length == AES_BLOCK_SIZE)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001085 msg = PAIRWISE_4;
1086 msgtxt = "4/4 Pairwise";
1087 } else {
1088 msg = PAIRWISE_2;
1089 msgtxt = "2/4 Pairwise";
1090 }
1091
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001092 if (msg == REQUEST || msg == PAIRWISE_2 || msg == PAIRWISE_4 ||
1093 msg == GROUP_2) {
1094 u16 ver = key_info & WPA_KEY_INFO_TYPE_MASK;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001095 if (sm->pairwise == WPA_CIPHER_CCMP ||
1096 sm->pairwise == WPA_CIPHER_GCMP) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001097 if (wpa_use_cmac(sm->wpa_key_mgmt) &&
1098 !wpa_use_akm_defined(sm->wpa_key_mgmt) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001099 ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) {
1100 wpa_auth_logger(wpa_auth, sm->addr,
1101 LOGGER_WARNING,
Hai Shalomfdcde762020-04-02 11:19:20 -07001102 "advertised support for AES-128-CMAC, but did not use it");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001103 return;
1104 }
1105
Roshan Pius3a1667e2018-07-03 15:17:14 -07001106 if (!wpa_use_cmac(sm->wpa_key_mgmt) &&
1107 !wpa_use_akm_defined(sm->wpa_key_mgmt) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001108 ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
1109 wpa_auth_logger(wpa_auth, sm->addr,
1110 LOGGER_WARNING,
Hai Shalomfdcde762020-04-02 11:19:20 -07001111 "did not use HMAC-SHA1-AES with CCMP/GCMP");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001112 return;
1113 }
1114 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001115
Roshan Pius3a1667e2018-07-03 15:17:14 -07001116 if (wpa_use_akm_defined(sm->wpa_key_mgmt) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001117 ver != WPA_KEY_INFO_TYPE_AKM_DEFINED) {
1118 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING,
1119 "did not use EAPOL-Key descriptor version 0 as required for AKM-defined cases");
1120 return;
1121 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001122 }
1123
1124 if (key_info & WPA_KEY_INFO_REQUEST) {
1125 if (sm->req_replay_counter_used &&
1126 os_memcmp(key->replay_counter, sm->req_replay_counter,
1127 WPA_REPLAY_COUNTER_LEN) <= 0) {
1128 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING,
Hai Shalomfdcde762020-04-02 11:19:20 -07001129 "received EAPOL-Key request with replayed counter");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001130 return;
1131 }
1132 }
1133
1134 if (!(key_info & WPA_KEY_INFO_REQUEST) &&
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001135 !wpa_replay_counter_valid(sm->key_replay, key->replay_counter)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001136 int i;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001137
1138 if (msg == PAIRWISE_2 &&
1139 wpa_replay_counter_valid(sm->prev_key_replay,
1140 key->replay_counter) &&
1141 sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING &&
1142 os_memcmp(sm->SNonce, key->key_nonce, WPA_NONCE_LEN) != 0)
1143 {
1144 /*
1145 * Some supplicant implementations (e.g., Windows XP
1146 * WZC) update SNonce for each EAPOL-Key 2/4. This
1147 * breaks the workaround on accepting any of the
1148 * pending requests, so allow the SNonce to be updated
1149 * even if we have already sent out EAPOL-Key 3/4.
1150 */
1151 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07001152 "Process SNonce update from STA based on retransmitted EAPOL-Key 1/4");
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001153 sm->update_snonce = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001154 os_memcpy(sm->alt_SNonce, sm->SNonce, WPA_NONCE_LEN);
Hai Shalome21d4e82020-04-29 16:34:06 -07001155 sm->alt_snonce_valid = true;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001156 os_memcpy(sm->alt_replay_counter,
1157 sm->key_replay[0].counter,
1158 WPA_REPLAY_COUNTER_LEN);
1159 goto continue_processing;
1160 }
1161
1162 if (msg == PAIRWISE_4 && sm->alt_snonce_valid &&
1163 sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING &&
1164 os_memcmp(key->replay_counter, sm->alt_replay_counter,
1165 WPA_REPLAY_COUNTER_LEN) == 0) {
1166 /*
1167 * Supplicant may still be using the old SNonce since
1168 * there was two EAPOL-Key 2/4 messages and they had
1169 * different SNonce values.
1170 */
1171 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
1172 "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 -08001173 goto continue_processing;
1174 }
1175
1176 if (msg == PAIRWISE_2 &&
1177 wpa_replay_counter_valid(sm->prev_key_replay,
1178 key->replay_counter) &&
1179 sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING) {
1180 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07001181 "ignore retransmitted EAPOL-Key %s - SNonce did not change",
1182 msgtxt);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001183 } else {
1184 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07001185 "received EAPOL-Key %s with unexpected replay counter",
1186 msgtxt);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001187 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001188 for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) {
1189 if (!sm->key_replay[i].valid)
1190 break;
1191 wpa_hexdump(MSG_DEBUG, "pending replay counter",
1192 sm->key_replay[i].counter,
1193 WPA_REPLAY_COUNTER_LEN);
1194 }
1195 wpa_hexdump(MSG_DEBUG, "received replay counter",
1196 key->replay_counter, WPA_REPLAY_COUNTER_LEN);
1197 return;
1198 }
1199
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001200continue_processing:
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001201#ifdef CONFIG_FILS
1202 if (sm->wpa == WPA_VERSION_WPA2 && mic_len == 0 &&
1203 !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
1204 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
1205 "WPA: Encr Key Data bit not set even though AEAD cipher is supposed to be used - drop frame");
1206 return;
1207 }
1208#endif /* CONFIG_FILS */
1209
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001210 switch (msg) {
1211 case PAIRWISE_2:
1212 if (sm->wpa_ptk_state != WPA_PTK_PTKSTART &&
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001213 sm->wpa_ptk_state != WPA_PTK_PTKCALCNEGOTIATING &&
1214 (!sm->update_snonce ||
1215 sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001216 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001217 "received EAPOL-Key msg 2/4 in invalid state (%d) - dropped",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001218 sm->wpa_ptk_state);
1219 return;
1220 }
1221 random_add_randomness(key->key_nonce, WPA_NONCE_LEN);
1222 if (sm->group->reject_4way_hs_for_entropy) {
1223 /*
1224 * The system did not have enough entropy to generate
1225 * strong random numbers. Reject the first 4-way
1226 * handshake(s) and collect some entropy based on the
1227 * information from it. Once enough entropy is
1228 * available, the next atempt will trigger GMK/Key
1229 * Counter update and the station will be allowed to
1230 * continue.
1231 */
Hai Shalomfdcde762020-04-02 11:19:20 -07001232 wpa_printf(MSG_DEBUG,
1233 "WPA: Reject 4-way handshake to collect more entropy for random number generation");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001234 random_mark_pool_ready();
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001235 wpa_sta_disconnect(wpa_auth, sm->addr,
1236 WLAN_REASON_PREV_AUTH_NOT_VALID);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001237 return;
1238 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001239 break;
1240 case PAIRWISE_4:
1241 if (sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING ||
1242 !sm->PTK_valid) {
1243 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001244 "received EAPOL-Key msg 4/4 in invalid state (%d) - dropped",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001245 sm->wpa_ptk_state);
1246 return;
1247 }
1248 break;
1249 case GROUP_2:
1250 if (sm->wpa_ptk_group_state != WPA_PTK_GROUP_REKEYNEGOTIATING
1251 || !sm->PTK_valid) {
1252 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001253 "received EAPOL-Key msg 2/2 in invalid state (%d) - dropped",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001254 sm->wpa_ptk_group_state);
1255 return;
1256 }
1257 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001258 case REQUEST:
1259 break;
1260 }
1261
1262 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
1263 "received EAPOL-Key frame (%s)", msgtxt);
1264
1265 if (key_info & WPA_KEY_INFO_ACK) {
1266 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
1267 "received invalid EAPOL-Key: Key Ack set");
1268 return;
1269 }
1270
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001271 if (!wpa_key_mgmt_fils(sm->wpa_key_mgmt) &&
1272 !(key_info & WPA_KEY_INFO_MIC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001273 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
1274 "received invalid EAPOL-Key: Key MIC not set");
1275 return;
1276 }
1277
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001278#ifdef CONFIG_FILS
1279 if (wpa_key_mgmt_fils(sm->wpa_key_mgmt) &&
1280 (key_info & WPA_KEY_INFO_MIC)) {
1281 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
1282 "received invalid EAPOL-Key: Key MIC set");
1283 return;
1284 }
1285#endif /* CONFIG_FILS */
1286
Hai Shalome21d4e82020-04-29 16:34:06 -07001287 sm->MICVerified = false;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001288 if (sm->PTK_valid && !sm->update_snonce) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001289 if (mic_len &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001290 wpa_verify_key_mic(sm->wpa_key_mgmt, sm->pmk_len, &sm->PTK,
1291 data, data_len) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001292 (msg != PAIRWISE_4 || !sm->alt_snonce_valid ||
1293 wpa_try_alt_snonce(sm, data, data_len))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001294 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
1295 "received EAPOL-Key with invalid MIC");
Hai Shalom74f70d42019-02-11 14:42:39 -08001296#ifdef TEST_FUZZ
1297 wpa_printf(MSG_INFO,
1298 "TEST: Ignore Key MIC failure for fuzz testing");
1299 goto continue_fuzz;
1300#endif /* TEST_FUZZ */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001301 return;
1302 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001303#ifdef CONFIG_FILS
1304 if (!mic_len &&
1305 wpa_aead_decrypt(sm, &sm->PTK, data, data_len,
1306 &key_data_length) < 0) {
1307 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
1308 "received EAPOL-Key with invalid MIC");
Hai Shalom74f70d42019-02-11 14:42:39 -08001309#ifdef TEST_FUZZ
1310 wpa_printf(MSG_INFO,
1311 "TEST: Ignore Key MIC failure for fuzz testing");
1312 goto continue_fuzz;
1313#endif /* TEST_FUZZ */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001314 return;
1315 }
1316#endif /* CONFIG_FILS */
Hai Shalom74f70d42019-02-11 14:42:39 -08001317#ifdef TEST_FUZZ
1318 continue_fuzz:
1319#endif /* TEST_FUZZ */
Hai Shalome21d4e82020-04-29 16:34:06 -07001320 sm->MICVerified = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001321 eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm);
1322 sm->pending_1_of_4_timeout = 0;
1323 }
1324
1325 if (key_info & WPA_KEY_INFO_REQUEST) {
1326 if (sm->MICVerified) {
1327 sm->req_replay_counter_used = 1;
1328 os_memcpy(sm->req_replay_counter, key->replay_counter,
1329 WPA_REPLAY_COUNTER_LEN);
1330 } else {
1331 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001332 "received EAPOL-Key request with invalid MIC");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001333 return;
1334 }
1335
1336 /*
1337 * TODO: should decrypt key data field if encryption was used;
1338 * even though MAC address KDE is not normally encrypted,
1339 * supplicant is allowed to encrypt it.
1340 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001341 if (key_info & WPA_KEY_INFO_ERROR) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001342 if (wpa_receive_error_report(
1343 wpa_auth, sm,
1344 !(key_info & WPA_KEY_INFO_KEY_TYPE)) > 0)
1345 return; /* STA entry was removed */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001346 } else if (key_info & WPA_KEY_INFO_KEY_TYPE) {
1347 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001348 "received EAPOL-Key Request for new 4-Way Handshake");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001349 wpa_request_new_ptk(sm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001350 } else if (key_data_length > 0 &&
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001351 wpa_parse_kde_ies(key_data, key_data_length,
1352 &kde) == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001353 kde.mac_addr) {
1354 } else {
1355 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalomfdcde762020-04-02 11:19:20 -07001356 "received EAPOL-Key Request for GTK rekeying");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001357 eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL);
1358 wpa_rekey_gtk(wpa_auth, NULL);
1359 }
1360 } else {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001361 /* Do not allow the same key replay counter to be reused. */
1362 wpa_replay_counter_mark_invalid(sm->key_replay,
1363 key->replay_counter);
1364
1365 if (msg == PAIRWISE_2) {
1366 /*
1367 * Maintain a copy of the pending EAPOL-Key frames in
1368 * case the EAPOL-Key frame was retransmitted. This is
1369 * needed to allow EAPOL-Key msg 2/4 reply to another
1370 * pending msg 1/4 to update the SNonce to work around
1371 * unexpected supplicant behavior.
1372 */
1373 os_memcpy(sm->prev_key_replay, sm->key_replay,
1374 sizeof(sm->key_replay));
1375 } else {
1376 os_memset(sm->prev_key_replay, 0,
1377 sizeof(sm->prev_key_replay));
1378 }
1379
1380 /*
1381 * Make sure old valid counters are not accepted anymore and
1382 * do not get copied again.
1383 */
1384 wpa_replay_counter_mark_invalid(sm->key_replay, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001385 }
1386
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001387 os_free(sm->last_rx_eapol_key);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001388 sm->last_rx_eapol_key = os_memdup(data, data_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07001389 if (!sm->last_rx_eapol_key)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001390 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001391 sm->last_rx_eapol_key_len = data_len;
1392
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001393 sm->rx_eapol_key_secure = !!(key_info & WPA_KEY_INFO_SECURE);
Hai Shalome21d4e82020-04-29 16:34:06 -07001394 sm->EAPOLKeyReceived = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001395 sm->EAPOLKeyPairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE);
1396 sm->EAPOLKeyRequest = !!(key_info & WPA_KEY_INFO_REQUEST);
1397 os_memcpy(sm->SNonce, key->key_nonce, WPA_NONCE_LEN);
1398 wpa_sm_step(sm);
1399}
1400
1401
1402static int wpa_gmk_to_gtk(const u8 *gmk, const char *label, const u8 *addr,
1403 const u8 *gnonce, u8 *gtk, size_t gtk_len)
1404{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001405 u8 data[ETH_ALEN + WPA_NONCE_LEN + 8 + WPA_GTK_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001406 u8 *pos;
1407 int ret = 0;
1408
1409 /* GTK = PRF-X(GMK, "Group key expansion",
1410 * AA || GNonce || Time || random data)
1411 * The example described in the IEEE 802.11 standard uses only AA and
1412 * GNonce as inputs here. Add some more entropy since this derivation
1413 * is done only at the Authenticator and as such, does not need to be
1414 * exactly same.
1415 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001416 os_memset(data, 0, sizeof(data));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001417 os_memcpy(data, addr, ETH_ALEN);
1418 os_memcpy(data + ETH_ALEN, gnonce, WPA_NONCE_LEN);
1419 pos = data + ETH_ALEN + WPA_NONCE_LEN;
1420 wpa_get_ntp_timestamp(pos);
Hai Shalom74f70d42019-02-11 14:42:39 -08001421#ifdef TEST_FUZZ
1422 os_memset(pos, 0xef, 8);
1423#endif /* TEST_FUZZ */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001424 pos += 8;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001425 if (random_get_bytes(pos, gtk_len) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001426 ret = -1;
1427
Roshan Pius3a1667e2018-07-03 15:17:14 -07001428#ifdef CONFIG_SHA384
1429 if (sha384_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data),
1430 gtk, gtk_len) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001431 ret = -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001432#else /* CONFIG_SHA384 */
1433#ifdef CONFIG_SHA256
1434 if (sha256_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data),
1435 gtk, gtk_len) < 0)
1436 ret = -1;
1437#else /* CONFIG_SHA256 */
1438 if (sha1_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data),
1439 gtk, gtk_len) < 0)
1440 ret = -1;
1441#endif /* CONFIG_SHA256 */
1442#endif /* CONFIG_SHA384 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001443
Hai Shalom81f62d82019-07-22 12:10:00 -07001444 forced_memzero(data, sizeof(data));
1445
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001446 return ret;
1447}
1448
1449
1450static void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx)
1451{
1452 struct wpa_authenticator *wpa_auth = eloop_ctx;
1453 struct wpa_state_machine *sm = timeout_ctx;
1454
1455 sm->pending_1_of_4_timeout = 0;
1456 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "EAPOL-Key timeout");
Hai Shalome21d4e82020-04-29 16:34:06 -07001457 sm->TimeoutEvt = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001458 wpa_sm_step(sm);
1459}
1460
1461
1462void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
1463 struct wpa_state_machine *sm, int key_info,
1464 const u8 *key_rsc, const u8 *nonce,
1465 const u8 *kde, size_t kde_len,
1466 int keyidx, int encr, int force_version)
1467{
Hai Shalomfdcde762020-04-02 11:19:20 -07001468 struct wpa_auth_config *conf = &wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001469 struct ieee802_1x_hdr *hdr;
1470 struct wpa_eapol_key *key;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001471 size_t len, mic_len, keyhdrlen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001472 int alg;
1473 int key_data_len, pad_len = 0;
1474 u8 *buf, *pos;
1475 int version, pairwise;
1476 int i;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001477 u8 *key_mic, *key_data;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001478
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001479 mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001480 keyhdrlen = sizeof(*key) + mic_len + 2;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001481
1482 len = sizeof(struct ieee802_1x_hdr) + keyhdrlen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001483
1484 if (force_version)
1485 version = force_version;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001486 else if (wpa_use_akm_defined(sm->wpa_key_mgmt))
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001487 version = WPA_KEY_INFO_TYPE_AKM_DEFINED;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001488 else if (wpa_use_cmac(sm->wpa_key_mgmt))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001489 version = WPA_KEY_INFO_TYPE_AES_128_CMAC;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001490 else if (sm->pairwise != WPA_CIPHER_TKIP)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001491 version = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;
1492 else
1493 version = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
1494
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001495 pairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001496
Hai Shalomfdcde762020-04-02 11:19:20 -07001497 wpa_printf(MSG_DEBUG,
1498 "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 -07001499 version,
1500 (key_info & WPA_KEY_INFO_SECURE) ? 1 : 0,
1501 (key_info & WPA_KEY_INFO_MIC) ? 1 : 0,
1502 (key_info & WPA_KEY_INFO_ACK) ? 1 : 0,
1503 (key_info & WPA_KEY_INFO_INSTALL) ? 1 : 0,
Hai Shalomfdcde762020-04-02 11:19:20 -07001504 pairwise, kde_len, keyidx, encr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001505
1506 key_data_len = kde_len;
1507
1508 if ((version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
Roshan Pius3a1667e2018-07-03 15:17:14 -07001509 wpa_use_aes_key_wrap(sm->wpa_key_mgmt) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001510 version == WPA_KEY_INFO_TYPE_AES_128_CMAC) && encr) {
1511 pad_len = key_data_len % 8;
1512 if (pad_len)
1513 pad_len = 8 - pad_len;
1514 key_data_len += pad_len + 8;
1515 }
1516
1517 len += key_data_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001518 if (!mic_len && encr)
1519 len += AES_BLOCK_SIZE;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001520
1521 hdr = os_zalloc(len);
Hai Shalomfdcde762020-04-02 11:19:20 -07001522 if (!hdr)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001523 return;
Hai Shalomfdcde762020-04-02 11:19:20 -07001524 hdr->version = conf->eapol_version;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001525 hdr->type = IEEE802_1X_TYPE_EAPOL_KEY;
1526 hdr->length = host_to_be16(len - sizeof(*hdr));
1527 key = (struct wpa_eapol_key *) (hdr + 1);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001528 key_mic = (u8 *) (key + 1);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001529 key_data = ((u8 *) (hdr + 1)) + keyhdrlen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001530
1531 key->type = sm->wpa == WPA_VERSION_WPA2 ?
1532 EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
1533 key_info |= version;
1534 if (encr && sm->wpa == WPA_VERSION_WPA2)
1535 key_info |= WPA_KEY_INFO_ENCR_KEY_DATA;
1536 if (sm->wpa != WPA_VERSION_WPA2)
1537 key_info |= keyidx << WPA_KEY_INFO_KEY_INDEX_SHIFT;
1538 WPA_PUT_BE16(key->key_info, key_info);
1539
Hai Shalomfdcde762020-04-02 11:19:20 -07001540 alg = pairwise ? sm->pairwise : conf->wpa_group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001541 if (sm->wpa == WPA_VERSION_WPA2 && !pairwise)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001542 WPA_PUT_BE16(key->key_length, 0);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001543 else
1544 WPA_PUT_BE16(key->key_length, wpa_cipher_key_len(alg));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001545
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001546 for (i = RSNA_MAX_EAPOL_RETRIES - 1; i > 0; i--) {
1547 sm->key_replay[i].valid = sm->key_replay[i - 1].valid;
1548 os_memcpy(sm->key_replay[i].counter,
1549 sm->key_replay[i - 1].counter,
1550 WPA_REPLAY_COUNTER_LEN);
1551 }
1552 inc_byte_array(sm->key_replay[0].counter, WPA_REPLAY_COUNTER_LEN);
1553 os_memcpy(key->replay_counter, sm->key_replay[0].counter,
1554 WPA_REPLAY_COUNTER_LEN);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001555 wpa_hexdump(MSG_DEBUG, "WPA: Replay Counter",
1556 key->replay_counter, WPA_REPLAY_COUNTER_LEN);
Hai Shalome21d4e82020-04-29 16:34:06 -07001557 sm->key_replay[0].valid = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001558
1559 if (nonce)
1560 os_memcpy(key->key_nonce, nonce, WPA_NONCE_LEN);
1561
1562 if (key_rsc)
1563 os_memcpy(key->key_rsc, key_rsc, WPA_KEY_RSC_LEN);
1564
1565 if (kde && !encr) {
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001566 os_memcpy(key_data, kde, kde_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001567 WPA_PUT_BE16(key_mic + mic_len, kde_len);
1568#ifdef CONFIG_FILS
Roshan Pius3a1667e2018-07-03 15:17:14 -07001569 } else if (!mic_len && kde) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001570 const u8 *aad[1];
1571 size_t aad_len[1];
1572
1573 WPA_PUT_BE16(key_mic, AES_BLOCK_SIZE + kde_len);
1574 wpa_hexdump_key(MSG_DEBUG, "Plaintext EAPOL-Key Key Data",
1575 kde, kde_len);
1576
1577 wpa_hexdump_key(MSG_DEBUG, "WPA: KEK",
1578 sm->PTK.kek, sm->PTK.kek_len);
1579 /* AES-SIV AAD from EAPOL protocol version field (inclusive) to
1580 * to Key Data (exclusive). */
1581 aad[0] = (u8 *) hdr;
1582 aad_len[0] = key_mic + 2 - (u8 *) hdr;
1583 if (aes_siv_encrypt(sm->PTK.kek, sm->PTK.kek_len, kde, kde_len,
1584 1, aad, aad_len, key_mic + 2) < 0) {
1585 wpa_printf(MSG_DEBUG, "WPA: AES-SIV encryption failed");
1586 return;
1587 }
1588
1589 wpa_hexdump(MSG_DEBUG, "WPA: Encrypted Key Data from SIV",
1590 key_mic + 2, AES_BLOCK_SIZE + kde_len);
1591#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001592 } else if (encr && kde) {
1593 buf = os_zalloc(key_data_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07001594 if (!buf) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001595 os_free(hdr);
1596 return;
1597 }
1598 pos = buf;
1599 os_memcpy(pos, kde, kde_len);
1600 pos += kde_len;
1601
1602 if (pad_len)
1603 *pos++ = 0xdd;
1604
1605 wpa_hexdump_key(MSG_DEBUG, "Plaintext EAPOL-Key Key Data",
1606 buf, key_data_len);
1607 if (version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
Roshan Pius3a1667e2018-07-03 15:17:14 -07001608 wpa_use_aes_key_wrap(sm->wpa_key_mgmt) ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001609 version == WPA_KEY_INFO_TYPE_AES_128_CMAC) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001610 wpa_printf(MSG_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07001611 "WPA: Encrypt Key Data using AES-WRAP (KEK length %zu)",
1612 sm->PTK.kek_len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001613 if (aes_wrap(sm->PTK.kek, sm->PTK.kek_len,
1614 (key_data_len - 8) / 8, buf, key_data)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001615 os_free(hdr);
1616 os_free(buf);
1617 return;
1618 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001619 WPA_PUT_BE16(key_mic + mic_len, key_data_len);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001620#ifndef CONFIG_NO_RC4
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001621 } else if (sm->PTK.kek_len == 16) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001622 u8 ek[32];
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001623
1624 wpa_printf(MSG_DEBUG,
1625 "WPA: Encrypt Key Data using RC4");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001626 os_memcpy(key->key_iv,
1627 sm->group->Counter + WPA_NONCE_LEN - 16, 16);
1628 inc_byte_array(sm->group->Counter, WPA_NONCE_LEN);
1629 os_memcpy(ek, key->key_iv, 16);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001630 os_memcpy(ek + 16, sm->PTK.kek, sm->PTK.kek_len);
1631 os_memcpy(key_data, buf, key_data_len);
1632 rc4_skip(ek, 32, 256, key_data, key_data_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001633 WPA_PUT_BE16(key_mic + mic_len, key_data_len);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001634#endif /* CONFIG_NO_RC4 */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001635 } else {
1636 os_free(hdr);
1637 os_free(buf);
1638 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001639 }
1640 os_free(buf);
1641 }
1642
1643 if (key_info & WPA_KEY_INFO_MIC) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001644 if (!sm->PTK_valid || !mic_len) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001645 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07001646 "PTK not valid when sending EAPOL-Key frame");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001647 os_free(hdr);
1648 return;
1649 }
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001650
Roshan Pius3a1667e2018-07-03 15:17:14 -07001651 if (wpa_eapol_key_mic(sm->PTK.kck, sm->PTK.kck_len,
1652 sm->wpa_key_mgmt, version,
1653 (u8 *) hdr, len, key_mic) < 0) {
1654 os_free(hdr);
1655 return;
1656 }
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001657#ifdef CONFIG_TESTING_OPTIONS
1658 if (!pairwise &&
Hai Shalomfdcde762020-04-02 11:19:20 -07001659 conf->corrupt_gtk_rekey_mic_probability > 0.0 &&
1660 drand48() < conf->corrupt_gtk_rekey_mic_probability) {
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001661 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
1662 "Corrupting group EAPOL-Key Key MIC");
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001663 key_mic[0]++;
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001664 }
1665#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001666 }
1667
Hai Shalomfdcde762020-04-02 11:19:20 -07001668 wpa_auth_set_eapol(wpa_auth, sm->addr, WPA_EAPOL_inc_EapolFramesTx, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001669 wpa_auth_send_eapol(wpa_auth, sm->addr, (u8 *) hdr, len,
Kai Shie75b0652020-11-24 20:31:29 -08001670 sm->pairwise_set);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001671 os_free(hdr);
1672}
1673
1674
1675static void wpa_send_eapol(struct wpa_authenticator *wpa_auth,
1676 struct wpa_state_machine *sm, int key_info,
1677 const u8 *key_rsc, const u8 *nonce,
1678 const u8 *kde, size_t kde_len,
1679 int keyidx, int encr)
1680{
1681 int timeout_ms;
1682 int pairwise = key_info & WPA_KEY_INFO_KEY_TYPE;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001683 u32 ctr;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001684
Hai Shalomfdcde762020-04-02 11:19:20 -07001685 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001686 return;
1687
1688 __wpa_send_eapol(wpa_auth, sm, key_info, key_rsc, nonce, kde, kde_len,
1689 keyidx, encr, 0);
1690
1691 ctr = pairwise ? sm->TimeoutCtr : sm->GTimeoutCtr;
1692 if (ctr == 1 && wpa_auth->conf.tx_status)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001693 timeout_ms = pairwise ? eapol_key_timeout_first :
1694 eapol_key_timeout_first_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001695 else
1696 timeout_ms = eapol_key_timeout_subseq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001697 if (wpa_auth->conf.wpa_disable_eapol_key_retries &&
1698 (!pairwise || (key_info & WPA_KEY_INFO_MIC)))
1699 timeout_ms = eapol_key_timeout_no_retrans;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001700 if (pairwise && ctr == 1 && !(key_info & WPA_KEY_INFO_MIC))
1701 sm->pending_1_of_4_timeout = 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08001702#ifdef TEST_FUZZ
1703 timeout_ms = 1;
1704#endif /* TEST_FUZZ */
Kai Shie75b0652020-11-24 20:31:29 -08001705#ifdef CONFIG_TESTING_OPTIONS
1706 if(wpa_auth->conf.enable_eapol_large_timeout) {
1707 timeout_ms = 50 * 1000;
1708 }
1709#endif
Hai Shalomfdcde762020-04-02 11:19:20 -07001710 wpa_printf(MSG_DEBUG,
1711 "WPA: Use EAPOL-Key timeout of %u ms (retry counter %u)",
1712 timeout_ms, ctr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001713 eloop_register_timeout(timeout_ms / 1000, (timeout_ms % 1000) * 1000,
1714 wpa_send_eapol_timeout, wpa_auth, sm);
1715}
1716
1717
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001718static int wpa_verify_key_mic(int akmp, size_t pmk_len, struct wpa_ptk *PTK,
1719 u8 *data, size_t data_len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001720{
1721 struct ieee802_1x_hdr *hdr;
1722 struct wpa_eapol_key *key;
1723 u16 key_info;
1724 int ret = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001725 u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN], *mic_pos;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001726 size_t mic_len = wpa_mic_len(akmp, pmk_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001727
1728 if (data_len < sizeof(*hdr) + sizeof(*key))
1729 return -1;
1730
1731 hdr = (struct ieee802_1x_hdr *) data;
1732 key = (struct wpa_eapol_key *) (hdr + 1);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001733 mic_pos = (u8 *) (key + 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001734 key_info = WPA_GET_BE16(key->key_info);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001735 os_memcpy(mic, mic_pos, mic_len);
1736 os_memset(mic_pos, 0, mic_len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001737 if (wpa_eapol_key_mic(PTK->kck, PTK->kck_len, akmp,
1738 key_info & WPA_KEY_INFO_TYPE_MASK,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001739 data, data_len, mic_pos) ||
1740 os_memcmp_const(mic, mic_pos, mic_len) != 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001741 ret = -1;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001742 os_memcpy(mic_pos, mic, mic_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001743 return ret;
1744}
1745
1746
1747void wpa_remove_ptk(struct wpa_state_machine *sm)
1748{
Hai Shalome21d4e82020-04-29 16:34:06 -07001749 sm->PTK_valid = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001750 os_memset(&sm->PTK, 0, sizeof(sm->PTK));
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001751 if (wpa_auth_set_key(sm->wpa_auth, 0, WPA_ALG_NONE, sm->addr, 0, NULL,
Hai Shalomfdcde762020-04-02 11:19:20 -07001752 0, KEY_FLAG_PAIRWISE))
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001753 wpa_printf(MSG_DEBUG,
1754 "RSN: PTK removal from the driver failed");
Hai Shalomfdcde762020-04-02 11:19:20 -07001755 if (sm->use_ext_key_id &&
1756 wpa_auth_set_key(sm->wpa_auth, 0, WPA_ALG_NONE, sm->addr, 1, NULL,
1757 0, KEY_FLAG_PAIRWISE))
1758 wpa_printf(MSG_DEBUG,
1759 "RSN: PTK Key ID 1 removal from the driver failed");
Hai Shalome21d4e82020-04-29 16:34:06 -07001760 sm->pairwise_set = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001761 eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm);
1762}
1763
1764
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001765int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001766{
1767 int remove_ptk = 1;
1768
Hai Shalomfdcde762020-04-02 11:19:20 -07001769 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001770 return -1;
1771
1772 wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
1773 "event %d notification", event);
1774
1775 switch (event) {
1776 case WPA_AUTH:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001777#ifdef CONFIG_MESH
1778 /* PTKs are derived through AMPE */
1779 if (wpa_auth_start_ampe(sm->wpa_auth, sm->addr)) {
1780 /* not mesh */
1781 break;
1782 }
1783 return 0;
1784#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001785 case WPA_ASSOC:
1786 break;
1787 case WPA_DEAUTH:
1788 case WPA_DISASSOC:
Hai Shalome21d4e82020-04-29 16:34:06 -07001789 sm->DeauthenticationRequest = true;
Hai Shalom1dc4d202019-04-29 16:22:27 -07001790#ifdef CONFIG_IEEE80211R_AP
1791 os_memset(sm->PMK, 0, sizeof(sm->PMK));
1792 sm->pmk_len = 0;
1793 os_memset(sm->xxkey, 0, sizeof(sm->xxkey));
1794 sm->xxkey_len = 0;
Hai Shalom81f62d82019-07-22 12:10:00 -07001795 os_memset(sm->pmk_r1, 0, sizeof(sm->pmk_r1));
1796 sm->pmk_r1_len = 0;
Hai Shalom1dc4d202019-04-29 16:22:27 -07001797#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001798 break;
1799 case WPA_REAUTH:
1800 case WPA_REAUTH_EAPOL:
1801 if (!sm->started) {
1802 /*
1803 * When using WPS, we may end up here if the STA
1804 * manages to re-associate without the previous STA
1805 * entry getting removed. Consequently, we need to make
1806 * sure that the WPA state machines gets initialized
1807 * properly at this point.
1808 */
Hai Shalomfdcde762020-04-02 11:19:20 -07001809 wpa_printf(MSG_DEBUG,
1810 "WPA state machine had not been started - initialize now");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001811 sm->started = 1;
Hai Shalome21d4e82020-04-29 16:34:06 -07001812 sm->Init = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001813 if (wpa_sm_step(sm) == 1)
1814 return 1; /* should not really happen */
Hai Shalome21d4e82020-04-29 16:34:06 -07001815 sm->Init = false;
1816 sm->AuthenticationRequest = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001817 break;
1818 }
Hai Shalomfdcde762020-04-02 11:19:20 -07001819
1820 if (!sm->use_ext_key_id &&
1821 sm->wpa_auth->conf.wpa_deny_ptk0_rekey) {
1822 wpa_printf(MSG_INFO,
1823 "WPA: PTK0 rekey not allowed, disconnect "
1824 MACSTR, MAC2STR(sm->addr));
Hai Shalome21d4e82020-04-29 16:34:06 -07001825 sm->Disconnect = true;
Hai Shalomfdcde762020-04-02 11:19:20 -07001826 /* Try to encourage the STA to reconnect */
1827 sm->disconnect_reason =
1828 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA;
1829 break;
1830 }
1831
1832 if (sm->use_ext_key_id)
1833 sm->keyidx_active ^= 1; /* flip Key ID */
1834
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001835 if (sm->GUpdateStationKeys) {
1836 /*
1837 * Reauthentication cancels the pending group key
1838 * update for this STA.
1839 */
1840 sm->group->GKeyDoneStations--;
Hai Shalome21d4e82020-04-29 16:34:06 -07001841 sm->GUpdateStationKeys = false;
1842 sm->PtkGroupInit = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001843 }
Hai Shalome21d4e82020-04-29 16:34:06 -07001844 sm->ReAuthenticationRequest = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001845 break;
1846 case WPA_ASSOC_FT:
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001847#ifdef CONFIG_IEEE80211R_AP
Hai Shalomfdcde762020-04-02 11:19:20 -07001848 wpa_printf(MSG_DEBUG,
1849 "FT: Retry PTK configuration after association");
Hai Shalomb755a2a2020-04-23 21:49:02 -07001850 wpa_ft_install_ptk(sm, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001851
1852 /* Using FT protocol, not WPA auth state machine */
1853 sm->ft_completed = 1;
Hai Shalom81f62d82019-07-22 12:10:00 -07001854 wpa_auth_set_ptk_rekey_timer(sm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001855 return 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001856#else /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001857 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001858#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001859 case WPA_ASSOC_FILS:
1860#ifdef CONFIG_FILS
1861 wpa_printf(MSG_DEBUG,
1862 "FILS: TK configuration after association");
1863 fils_set_tk(sm);
1864 sm->fils_completed = 1;
1865 return 0;
1866#else /* CONFIG_FILS */
1867 break;
1868#endif /* CONFIG_FILS */
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02001869 case WPA_DRV_STA_REMOVED:
Hai Shalome21d4e82020-04-29 16:34:06 -07001870 sm->tk_already_set = false;
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02001871 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001872 }
1873
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001874#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001875 sm->ft_completed = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001876#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001877
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001878 if (sm->mgmt_frame_prot && event == WPA_AUTH)
1879 remove_ptk = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001880#ifdef CONFIG_FILS
1881 if (wpa_key_mgmt_fils(sm->wpa_key_mgmt) &&
1882 (event == WPA_AUTH || event == WPA_ASSOC))
1883 remove_ptk = 0;
1884#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001885
1886 if (remove_ptk) {
Hai Shalome21d4e82020-04-29 16:34:06 -07001887 sm->PTK_valid = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001888 os_memset(&sm->PTK, 0, sizeof(sm->PTK));
1889
1890 if (event != WPA_REAUTH_EAPOL)
1891 wpa_remove_ptk(sm);
1892 }
1893
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001894 if (sm->in_step_loop) {
1895 /*
1896 * wpa_sm_step() is already running - avoid recursive call to
1897 * it by making the existing loop process the new update.
1898 */
Hai Shalome21d4e82020-04-29 16:34:06 -07001899 sm->changed = true;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001900 return 0;
1901 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001902 return wpa_sm_step(sm);
1903}
1904
1905
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001906SM_STATE(WPA_PTK, INITIALIZE)
1907{
1908 SM_ENTRY_MA(WPA_PTK, INITIALIZE, wpa_ptk);
1909 if (sm->Init) {
1910 /* Init flag is not cleared here, so avoid busy
1911 * loop by claiming nothing changed. */
Hai Shalome21d4e82020-04-29 16:34:06 -07001912 sm->changed = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001913 }
1914
1915 sm->keycount = 0;
1916 if (sm->GUpdateStationKeys)
1917 sm->group->GKeyDoneStations--;
Hai Shalome21d4e82020-04-29 16:34:06 -07001918 sm->GUpdateStationKeys = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001919 if (sm->wpa == WPA_VERSION_WPA)
Hai Shalome21d4e82020-04-29 16:34:06 -07001920 sm->PInitAKeys = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001921 if (1 /* Unicast cipher supported AND (ESS OR ((IBSS or WDS) and
1922 * Local AA > Remote AA)) */) {
Hai Shalome21d4e82020-04-29 16:34:06 -07001923 sm->Pair = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001924 }
1925 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 0);
1926 wpa_remove_ptk(sm);
1927 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid, 0);
1928 sm->TimeoutCtr = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001929 if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
1930 sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP ||
1931 sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001932 wpa_auth_set_eapol(sm->wpa_auth, sm->addr,
1933 WPA_EAPOL_authorized, 0);
1934 }
1935}
1936
1937
1938SM_STATE(WPA_PTK, DISCONNECT)
1939{
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001940 u16 reason = sm->disconnect_reason;
1941
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001942 SM_ENTRY_MA(WPA_PTK, DISCONNECT, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07001943 sm->Disconnect = false;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001944 sm->disconnect_reason = 0;
1945 if (!reason)
1946 reason = WLAN_REASON_PREV_AUTH_NOT_VALID;
1947 wpa_sta_disconnect(sm->wpa_auth, sm->addr, reason);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001948}
1949
1950
1951SM_STATE(WPA_PTK, DISCONNECTED)
1952{
1953 SM_ENTRY_MA(WPA_PTK, DISCONNECTED, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07001954 sm->DeauthenticationRequest = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001955}
1956
1957
1958SM_STATE(WPA_PTK, AUTHENTICATION)
1959{
1960 SM_ENTRY_MA(WPA_PTK, AUTHENTICATION, wpa_ptk);
1961 os_memset(&sm->PTK, 0, sizeof(sm->PTK));
Hai Shalome21d4e82020-04-29 16:34:06 -07001962 sm->PTK_valid = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001963 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portControl_Auto,
1964 1);
1965 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 1);
Hai Shalome21d4e82020-04-29 16:34:06 -07001966 sm->AuthenticationRequest = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001967}
1968
1969
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001970static void wpa_group_ensure_init(struct wpa_authenticator *wpa_auth,
1971 struct wpa_group *group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001972{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001973 if (group->first_sta_seen)
1974 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001975 /*
1976 * System has run bit further than at the time hostapd was started
1977 * potentially very early during boot up. This provides better chances
1978 * of collecting more randomness on embedded systems. Re-initialize the
1979 * GMK and Counter here to improve their strength if there was not
1980 * enough entropy available immediately after system startup.
1981 */
Hai Shalomfdcde762020-04-02 11:19:20 -07001982 wpa_printf(MSG_DEBUG,
1983 "WPA: Re-initialize GMK/Counter on first station");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001984 if (random_pool_ready() != 1) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001985 wpa_printf(MSG_INFO,
1986 "WPA: Not enough entropy in random pool to proceed - reject first 4-way handshake");
Hai Shalome21d4e82020-04-29 16:34:06 -07001987 group->reject_4way_hs_for_entropy = true;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001988 } else {
Hai Shalome21d4e82020-04-29 16:34:06 -07001989 group->first_sta_seen = true;
1990 group->reject_4way_hs_for_entropy = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001991 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001992
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001993 if (wpa_group_init_gmk_and_counter(wpa_auth, group) < 0 ||
1994 wpa_gtk_update(wpa_auth, group) < 0 ||
1995 wpa_group_config_group_keys(wpa_auth, group) < 0) {
1996 wpa_printf(MSG_INFO, "WPA: GMK/GTK setup failed");
Hai Shalome21d4e82020-04-29 16:34:06 -07001997 group->first_sta_seen = false;
1998 group->reject_4way_hs_for_entropy = true;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001999 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002000}
2001
2002
2003SM_STATE(WPA_PTK, AUTHENTICATION2)
2004{
2005 SM_ENTRY_MA(WPA_PTK, AUTHENTICATION2, wpa_ptk);
2006
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002007 wpa_group_ensure_init(sm->wpa_auth, sm->group);
Hai Shalome21d4e82020-04-29 16:34:06 -07002008 sm->ReAuthenticationRequest = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002009
Dmitry Shmidt04949592012-07-19 12:16:46 -07002010 /*
2011 * Definition of ANonce selection in IEEE Std 802.11i-2004 is somewhat
2012 * ambiguous. The Authenticator state machine uses a counter that is
2013 * incremented by one for each 4-way handshake. However, the security
2014 * analysis of 4-way handshake points out that unpredictable nonces
2015 * help in preventing precomputation attacks. Instead of the state
2016 * machine definition, use an unpredictable nonce value here to provide
2017 * stronger protection against potential precomputation attacks.
2018 */
2019 if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) {
Hai Shalomfdcde762020-04-02 11:19:20 -07002020 wpa_printf(MSG_ERROR,
2021 "WPA: Failed to get random data for ANonce.");
Hai Shalome21d4e82020-04-29 16:34:06 -07002022 sm->Disconnect = true;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002023 return;
2024 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002025 wpa_hexdump(MSG_DEBUG, "WPA: Assign ANonce", sm->ANonce,
2026 WPA_NONCE_LEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002027 /* IEEE 802.11i does not clear TimeoutCtr here, but this is more
2028 * logical place than INITIALIZE since AUTHENTICATION2 can be
2029 * re-entered on ReAuthenticationRequest without going through
2030 * INITIALIZE. */
2031 sm->TimeoutCtr = 0;
2032}
2033
2034
Jouni Malinen1420a892017-10-01 12:32:57 +03002035static int wpa_auth_sm_ptk_update(struct wpa_state_machine *sm)
2036{
2037 if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) {
2038 wpa_printf(MSG_ERROR,
2039 "WPA: Failed to get random data for ANonce");
Hai Shalome21d4e82020-04-29 16:34:06 -07002040 sm->Disconnect = true;
Jouni Malinen1420a892017-10-01 12:32:57 +03002041 return -1;
2042 }
2043 wpa_hexdump(MSG_DEBUG, "WPA: Assign new ANonce", sm->ANonce,
2044 WPA_NONCE_LEN);
2045 sm->TimeoutCtr = 0;
2046 return 0;
2047}
2048
2049
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002050SM_STATE(WPA_PTK, INITPMK)
2051{
2052 u8 msk[2 * PMK_LEN];
2053 size_t len = 2 * PMK_LEN;
2054
2055 SM_ENTRY_MA(WPA_PTK, INITPMK, wpa_ptk);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002056#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002057 sm->xxkey_len = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002058#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002059 if (sm->pmksa) {
2060 wpa_printf(MSG_DEBUG, "WPA: PMK from PMKSA cache");
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002061 os_memcpy(sm->PMK, sm->pmksa->pmk, sm->pmksa->pmk_len);
2062 sm->pmk_len = sm->pmksa->pmk_len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002063#ifdef CONFIG_DPP
2064 } else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP) {
2065 wpa_printf(MSG_DEBUG,
2066 "DPP: No PMKSA cache entry for STA - reject connection");
Hai Shalome21d4e82020-04-29 16:34:06 -07002067 sm->Disconnect = true;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002068 sm->disconnect_reason = WLAN_REASON_INVALID_PMKID;
2069 return;
2070#endif /* CONFIG_DPP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002071 } else if (wpa_auth_get_msk(sm->wpa_auth, sm->addr, msk, &len) == 0) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002072 unsigned int pmk_len;
2073
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002074 if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002075 pmk_len = PMK_LEN_SUITE_B_192;
2076 else
2077 pmk_len = PMK_LEN;
Hai Shalomfdcde762020-04-02 11:19:20 -07002078 wpa_printf(MSG_DEBUG,
2079 "WPA: PMK from EAPOL state machine (MSK len=%zu PMK len=%u)",
2080 len, pmk_len);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002081 if (len < pmk_len) {
2082 wpa_printf(MSG_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07002083 "WPA: MSK not long enough (%zu) to create PMK (%u)",
2084 len, pmk_len);
Hai Shalome21d4e82020-04-29 16:34:06 -07002085 sm->Disconnect = true;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002086 return;
2087 }
2088 os_memcpy(sm->PMK, msk, pmk_len);
2089 sm->pmk_len = pmk_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002090#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002091 if (len >= 2 * PMK_LEN) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002092 if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) {
2093 os_memcpy(sm->xxkey, msk, SHA384_MAC_LEN);
2094 sm->xxkey_len = SHA384_MAC_LEN;
2095 } else {
2096 os_memcpy(sm->xxkey, msk + PMK_LEN, PMK_LEN);
2097 sm->xxkey_len = PMK_LEN;
2098 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002099 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002100#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002101 } else {
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002102 wpa_printf(MSG_DEBUG, "WPA: Could not get PMK, get_msk: %p",
Paul Stewart092955c2017-02-06 09:13:09 -08002103 sm->wpa_auth->cb->get_msk);
Hai Shalome21d4e82020-04-29 16:34:06 -07002104 sm->Disconnect = true;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002105 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002106 }
Hai Shalom81f62d82019-07-22 12:10:00 -07002107 forced_memzero(msk, sizeof(msk));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002108
2109 sm->req_replay_counter_used = 0;
Hai Shalome21d4e82020-04-29 16:34:06 -07002110 /* IEEE 802.11i does not set keyRun to false, but not doing this
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002111 * will break reauthentication since EAPOL state machines may not be
2112 * get into AUTHENTICATING state that clears keyRun before WPA state
2113 * machine enters AUTHENTICATION2 state and goes immediately to INITPMK
2114 * state and takes PMK from the previously used AAA Key. This will
2115 * eventually fail in 4-Way Handshake because Supplicant uses PMK
Hai Shalome21d4e82020-04-29 16:34:06 -07002116 * derived from the new AAA Key. Setting keyRun = false here seems to
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002117 * be good workaround for this issue. */
Hai Shalome21d4e82020-04-29 16:34:06 -07002118 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyRun, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002119}
2120
2121
2122SM_STATE(WPA_PTK, INITPSK)
2123{
2124 const u8 *psk;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002125 size_t psk_len;
2126
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002127 SM_ENTRY_MA(WPA_PTK, INITPSK, wpa_ptk);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002128 psk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr, NULL,
Hai Shalom021b0b52019-04-10 11:17:58 -07002129 &psk_len, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002130 if (psk) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002131 os_memcpy(sm->PMK, psk, psk_len);
2132 sm->pmk_len = psk_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002133#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002134 os_memcpy(sm->xxkey, psk, PMK_LEN);
2135 sm->xxkey_len = PMK_LEN;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002136#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002137 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002138#ifdef CONFIG_SAE
2139 if (wpa_auth_uses_sae(sm) && sm->pmksa) {
2140 wpa_printf(MSG_DEBUG, "SAE: PMK from PMKSA cache");
2141 os_memcpy(sm->PMK, sm->pmksa->pmk, sm->pmksa->pmk_len);
2142 sm->pmk_len = sm->pmksa->pmk_len;
Hai Shalom021b0b52019-04-10 11:17:58 -07002143#ifdef CONFIG_IEEE80211R_AP
2144 os_memcpy(sm->xxkey, sm->pmksa->pmk, sm->pmksa->pmk_len);
2145 sm->xxkey_len = sm->pmksa->pmk_len;
2146#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002147 }
2148#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002149 sm->req_replay_counter_used = 0;
2150}
2151
2152
2153SM_STATE(WPA_PTK, PTKSTART)
2154{
2155 u8 buf[2 + RSN_SELECTOR_LEN + PMKID_LEN], *pmkid = NULL;
2156 size_t pmkid_len = 0;
2157
2158 SM_ENTRY_MA(WPA_PTK, PTKSTART, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07002159 sm->PTKRequest = false;
2160 sm->TimeoutEvt = false;
2161 sm->alt_snonce_valid = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002162
2163 sm->TimeoutCtr++;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002164 if (sm->TimeoutCtr > sm->wpa_auth->conf.wpa_pairwise_update_count) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002165 /* No point in sending the EAPOL-Key - we will disconnect
2166 * immediately following this. */
2167 return;
2168 }
2169
2170 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
2171 "sending 1/4 msg of 4-Way Handshake");
2172 /*
Hai Shalomce48b4a2018-09-05 11:41:35 -07002173 * For infrastructure BSS cases, it is better for the AP not to include
2174 * the PMKID KDE in EAPOL-Key msg 1/4 since it could be used to initiate
2175 * offline search for the passphrase/PSK without having to be able to
2176 * capture a 4-way handshake from a STA that has access to the network.
2177 *
2178 * For IBSS cases, addition of PMKID KDE could be considered even with
2179 * WPA2-PSK cases that use multiple PSKs, but only if there is a single
2180 * possible PSK for this STA. However, this should not be done unless
2181 * there is support for using that information on the supplicant side.
2182 * The concern about exposing PMKID unnecessarily in infrastructure BSS
2183 * cases would also apply here, but at least in the IBSS case, this
2184 * would cover a potential real use case.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002185 */
2186 if (sm->wpa == WPA_VERSION_WPA2 &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002187 (wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) ||
2188 (sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE && sm->pmksa) ||
2189 wpa_key_mgmt_sae(sm->wpa_key_mgmt)) &&
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002190 sm->wpa_key_mgmt != WPA_KEY_MGMT_OSEN) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002191 pmkid = buf;
2192 pmkid_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN;
2193 pmkid[0] = WLAN_EID_VENDOR_SPECIFIC;
2194 pmkid[1] = RSN_SELECTOR_LEN + PMKID_LEN;
2195 RSN_SELECTOR_PUT(&pmkid[2], RSN_KEY_DATA_PMKID);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002196 if (sm->pmksa) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002197 wpa_hexdump(MSG_DEBUG,
2198 "RSN: Message 1/4 PMKID from PMKSA entry",
2199 sm->pmksa->pmkid, PMKID_LEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002200 os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN],
2201 sm->pmksa->pmkid, PMKID_LEN);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002202 } else if (wpa_key_mgmt_suite_b(sm->wpa_key_mgmt)) {
2203 /* No KCK available to derive PMKID */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002204 wpa_printf(MSG_DEBUG,
2205 "RSN: No KCK available to derive PMKID for message 1/4");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002206 pmkid = NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -07002207#ifdef CONFIG_FILS
2208 } else if (wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
2209 if (sm->pmkid_set) {
2210 wpa_hexdump(MSG_DEBUG,
2211 "RSN: Message 1/4 PMKID from FILS/ERP",
2212 sm->pmkid, PMKID_LEN);
2213 os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN],
2214 sm->pmkid, PMKID_LEN);
2215 } else {
2216 /* No PMKID available */
2217 wpa_printf(MSG_DEBUG,
2218 "RSN: No FILS/ERP PMKID available for message 1/4");
2219 pmkid = NULL;
2220 }
2221#endif /* CONFIG_FILS */
2222#ifdef CONFIG_IEEE80211R_AP
2223 } else if (wpa_key_mgmt_ft(sm->wpa_key_mgmt) &&
2224 sm->ft_completed) {
2225 wpa_printf(MSG_DEBUG,
2226 "FT: No PMKID in message 1/4 when using FT protocol");
2227 pmkid = NULL;
Hai Shalom81f62d82019-07-22 12:10:00 -07002228#endif /* CONFIG_IEEE80211R_AP */
Roshan Pius3a1667e2018-07-03 15:17:14 -07002229#ifdef CONFIG_SAE
2230 } else if (wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
2231 if (sm->pmkid_set) {
2232 wpa_hexdump(MSG_DEBUG,
2233 "RSN: Message 1/4 PMKID from SAE",
2234 sm->pmkid, PMKID_LEN);
2235 os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN],
2236 sm->pmkid, PMKID_LEN);
2237 } else {
2238 /* No PMKID available */
2239 wpa_printf(MSG_DEBUG,
2240 "RSN: No SAE PMKID available for message 1/4");
2241 pmkid = NULL;
2242 }
2243#endif /* CONFIG_SAE */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002244 } else {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002245 /*
2246 * Calculate PMKID since no PMKSA cache entry was
2247 * available with pre-calculated PMKID.
2248 */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002249 rsn_pmkid(sm->PMK, sm->pmk_len, sm->wpa_auth->addr,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002250 sm->addr, &pmkid[2 + RSN_SELECTOR_LEN],
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002251 sm->wpa_key_mgmt);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002252 wpa_hexdump(MSG_DEBUG,
2253 "RSN: Message 1/4 PMKID derived from PMK",
2254 &pmkid[2 + RSN_SELECTOR_LEN], PMKID_LEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002255 }
2256 }
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002257 if (!pmkid)
2258 pmkid_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002259 wpa_send_eapol(sm->wpa_auth, sm,
2260 WPA_KEY_INFO_ACK | WPA_KEY_INFO_KEY_TYPE, NULL,
2261 sm->ANonce, pmkid, pmkid_len, 0, 0);
2262}
2263
2264
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002265static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002266 const u8 *pmk, unsigned int pmk_len,
Hai Shalomfdcde762020-04-02 11:19:20 -07002267 struct wpa_ptk *ptk, int force_sha256)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002268{
Hai Shalom021b0b52019-04-10 11:17:58 -07002269 const u8 *z = NULL;
2270 size_t z_len = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002271 int akmp;
Hai Shalom021b0b52019-04-10 11:17:58 -07002272
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002273#ifdef CONFIG_IEEE80211R_AP
Hai Shalom81f62d82019-07-22 12:10:00 -07002274 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
2275 if (sm->ft_completed) {
2276 u8 ptk_name[WPA_PMK_NAME_LEN];
2277
2278 return wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->pmk_r1_len,
2279 sm->SNonce, sm->ANonce,
2280 sm->addr, sm->wpa_auth->addr,
2281 sm->pmk_r1_name,
2282 ptk, ptk_name,
2283 sm->wpa_key_mgmt,
2284 sm->pairwise);
2285 }
2286 return wpa_auth_derive_ptk_ft(sm, ptk);
2287 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002288#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002289
Hai Shalom021b0b52019-04-10 11:17:58 -07002290#ifdef CONFIG_DPP2
2291 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP && sm->dpp_z) {
2292 z = wpabuf_head(sm->dpp_z);
2293 z_len = wpabuf_len(sm->dpp_z);
2294 }
2295#endif /* CONFIG_DPP2 */
2296
Hai Shalomfdcde762020-04-02 11:19:20 -07002297 akmp = sm->wpa_key_mgmt;
2298 if (force_sha256)
2299 akmp |= WPA_KEY_MGMT_PSK_SHA256;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002300 return wpa_pmk_to_ptk(pmk, pmk_len, "Pairwise key expansion",
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002301 sm->wpa_auth->addr, sm->addr, sm->ANonce, snonce,
Hai Shalomfdcde762020-04-02 11:19:20 -07002302 ptk, akmp, sm->pairwise, z, z_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002303}
2304
2305
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002306#ifdef CONFIG_FILS
2307
2308int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002309 size_t pmk_len, const u8 *snonce, const u8 *anonce,
2310 const u8 *dhss, size_t dhss_len,
2311 struct wpabuf *g_sta, struct wpabuf *g_ap)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002312{
2313 u8 ick[FILS_ICK_MAX_LEN];
2314 size_t ick_len;
2315 int res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002316 u8 fils_ft[FILS_FT_MAX_LEN];
2317 size_t fils_ft_len = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002318
2319 res = fils_pmk_to_ptk(pmk, pmk_len, sm->addr, sm->wpa_auth->addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002320 snonce, anonce, dhss, dhss_len,
2321 &sm->PTK, ick, &ick_len,
2322 sm->wpa_key_mgmt, sm->pairwise,
2323 fils_ft, &fils_ft_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002324 if (res < 0)
2325 return res;
Hai Shalome21d4e82020-04-29 16:34:06 -07002326 sm->PTK_valid = true;
2327 sm->tk_already_set = false;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002328
2329#ifdef CONFIG_IEEE80211R_AP
2330 if (fils_ft_len) {
2331 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
2332 struct wpa_auth_config *conf = &wpa_auth->conf;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002333 u8 pmk_r0[PMK_LEN_MAX], pmk_r0_name[WPA_PMK_NAME_LEN];
2334 int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002335
2336 if (wpa_derive_pmk_r0(fils_ft, fils_ft_len,
2337 conf->ssid, conf->ssid_len,
2338 conf->mobility_domain,
2339 conf->r0_key_holder,
2340 conf->r0_key_holder_len,
Roshan Pius3a1667e2018-07-03 15:17:14 -07002341 sm->addr, pmk_r0, pmk_r0_name,
2342 use_sha384) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002343 return -1;
2344
Roshan Pius3a1667e2018-07-03 15:17:14 -07002345 wpa_ft_store_pmk_fils(sm, pmk_r0, pmk_r0_name);
Hai Shalom81f62d82019-07-22 12:10:00 -07002346 forced_memzero(fils_ft, sizeof(fils_ft));
Hai Shalom021b0b52019-04-10 11:17:58 -07002347
2348 res = wpa_derive_pmk_r1_name(pmk_r0_name, conf->r1_key_holder,
2349 sm->addr, sm->pmk_r1_name,
2350 use_sha384);
Hai Shalom81f62d82019-07-22 12:10:00 -07002351 forced_memzero(pmk_r0, PMK_LEN_MAX);
Hai Shalom021b0b52019-04-10 11:17:58 -07002352 if (res < 0)
2353 return -1;
2354 wpa_hexdump(MSG_DEBUG, "FILS+FT: PMKR1Name", sm->pmk_r1_name,
2355 WPA_PMK_NAME_LEN);
2356 sm->pmk_r1_name_valid = 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002357 }
2358#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002359
2360 res = fils_key_auth_sk(ick, ick_len, snonce, anonce,
2361 sm->addr, sm->wpa_auth->addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002362 g_sta ? wpabuf_head(g_sta) : NULL,
2363 g_sta ? wpabuf_len(g_sta) : 0,
2364 g_ap ? wpabuf_head(g_ap) : NULL,
2365 g_ap ? wpabuf_len(g_ap) : 0,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002366 sm->wpa_key_mgmt, sm->fils_key_auth_sta,
2367 sm->fils_key_auth_ap,
2368 &sm->fils_key_auth_len);
Hai Shalom81f62d82019-07-22 12:10:00 -07002369 forced_memzero(ick, sizeof(ick));
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002370
2371 /* Store nonces for (Re)Association Request/Response frame processing */
2372 os_memcpy(sm->SNonce, snonce, FILS_NONCE_LEN);
2373 os_memcpy(sm->ANonce, anonce, FILS_NONCE_LEN);
2374
2375 return res;
2376}
2377
2378
2379static int wpa_aead_decrypt(struct wpa_state_machine *sm, struct wpa_ptk *ptk,
2380 u8 *buf, size_t buf_len, u16 *_key_data_len)
2381{
2382 struct ieee802_1x_hdr *hdr;
2383 struct wpa_eapol_key *key;
2384 u8 *pos;
2385 u16 key_data_len;
2386 u8 *tmp;
2387 const u8 *aad[1];
2388 size_t aad_len[1];
2389
2390 hdr = (struct ieee802_1x_hdr *) buf;
2391 key = (struct wpa_eapol_key *) (hdr + 1);
2392 pos = (u8 *) (key + 1);
2393 key_data_len = WPA_GET_BE16(pos);
2394 if (key_data_len < AES_BLOCK_SIZE ||
2395 key_data_len > buf_len - sizeof(*hdr) - sizeof(*key) - 2) {
2396 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO,
2397 "No room for AES-SIV data in the frame");
2398 return -1;
2399 }
2400 pos += 2; /* Pointing at the Encrypted Key Data field */
2401
2402 tmp = os_malloc(key_data_len);
2403 if (!tmp)
2404 return -1;
2405
2406 /* AES-SIV AAD from EAPOL protocol version field (inclusive) to
2407 * to Key Data (exclusive). */
2408 aad[0] = buf;
2409 aad_len[0] = pos - buf;
2410 if (aes_siv_decrypt(ptk->kek, ptk->kek_len, pos, key_data_len,
2411 1, aad, aad_len, tmp) < 0) {
2412 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO,
2413 "Invalid AES-SIV data in the frame");
2414 bin_clear_free(tmp, key_data_len);
2415 return -1;
2416 }
2417
2418 /* AEAD decryption and validation completed successfully */
2419 key_data_len -= AES_BLOCK_SIZE;
2420 wpa_hexdump_key(MSG_DEBUG, "WPA: Decrypted Key Data",
2421 tmp, key_data_len);
2422
2423 /* Replace Key Data field with the decrypted version */
2424 os_memcpy(pos, tmp, key_data_len);
2425 pos -= 2; /* Key Data Length field */
2426 WPA_PUT_BE16(pos, key_data_len);
2427 bin_clear_free(tmp, key_data_len);
2428 if (_key_data_len)
2429 *_key_data_len = key_data_len;
2430 return 0;
2431}
2432
2433
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002434const u8 * wpa_fils_validate_fils_session(struct wpa_state_machine *sm,
2435 const u8 *ies, size_t ies_len,
2436 const u8 *fils_session)
2437{
2438 const u8 *ie, *end;
2439 const u8 *session = NULL;
2440
2441 if (!wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
2442 wpa_printf(MSG_DEBUG,
2443 "FILS: Not a FILS AKM - reject association");
2444 return NULL;
2445 }
2446
2447 /* Verify Session element */
2448 ie = ies;
2449 end = ((const u8 *) ie) + ies_len;
2450 while (ie + 1 < end) {
2451 if (ie + 2 + ie[1] > end)
2452 break;
2453 if (ie[0] == WLAN_EID_EXTENSION &&
2454 ie[1] >= 1 + FILS_SESSION_LEN &&
2455 ie[2] == WLAN_EID_EXT_FILS_SESSION) {
2456 session = ie;
2457 break;
2458 }
2459 ie += 2 + ie[1];
2460 }
2461
2462 if (!session) {
2463 wpa_printf(MSG_DEBUG,
2464 "FILS: %s: Could not find FILS Session element in Assoc Req - reject",
2465 __func__);
2466 return NULL;
2467 }
2468
2469 if (!fils_session) {
2470 wpa_printf(MSG_DEBUG,
2471 "FILS: %s: Could not find FILS Session element in STA entry - reject",
2472 __func__);
2473 return NULL;
2474 }
2475
2476 if (os_memcmp(fils_session, session + 3, FILS_SESSION_LEN) != 0) {
2477 wpa_printf(MSG_DEBUG, "FILS: Session mismatch");
2478 wpa_hexdump(MSG_DEBUG, "FILS: Expected FILS Session",
2479 fils_session, FILS_SESSION_LEN);
2480 wpa_hexdump(MSG_DEBUG, "FILS: Received FILS Session",
2481 session + 3, FILS_SESSION_LEN);
2482 return NULL;
2483 }
2484 return session;
2485}
2486
2487
2488int wpa_fils_validate_key_confirm(struct wpa_state_machine *sm, const u8 *ies,
2489 size_t ies_len)
2490{
2491 struct ieee802_11_elems elems;
2492
2493 if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed) {
2494 wpa_printf(MSG_DEBUG,
2495 "FILS: Failed to parse decrypted elements");
2496 return -1;
2497 }
2498
2499 if (!elems.fils_session) {
2500 wpa_printf(MSG_DEBUG, "FILS: No FILS Session element");
2501 return -1;
2502 }
2503
2504 if (!elems.fils_key_confirm) {
2505 wpa_printf(MSG_DEBUG, "FILS: No FILS Key Confirm element");
2506 return -1;
2507 }
2508
2509 if (elems.fils_key_confirm_len != sm->fils_key_auth_len) {
2510 wpa_printf(MSG_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07002511 "FILS: Unexpected Key-Auth length %d (expected %zu)",
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002512 elems.fils_key_confirm_len,
Hai Shalomfdcde762020-04-02 11:19:20 -07002513 sm->fils_key_auth_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002514 return -1;
2515 }
2516
2517 if (os_memcmp(elems.fils_key_confirm, sm->fils_key_auth_sta,
2518 sm->fils_key_auth_len) != 0) {
2519 wpa_printf(MSG_DEBUG, "FILS: Key-Auth mismatch");
2520 wpa_hexdump(MSG_DEBUG, "FILS: Received Key-Auth",
2521 elems.fils_key_confirm, elems.fils_key_confirm_len);
2522 wpa_hexdump(MSG_DEBUG, "FILS: Expected Key-Auth",
2523 sm->fils_key_auth_sta, sm->fils_key_auth_len);
2524 return -1;
2525 }
2526
2527 return 0;
2528}
2529
2530
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002531int fils_decrypt_assoc(struct wpa_state_machine *sm, const u8 *fils_session,
2532 const struct ieee80211_mgmt *mgmt, size_t frame_len,
2533 u8 *pos, size_t left)
2534{
2535 u16 fc, stype;
2536 const u8 *end, *ie_start, *ie, *session, *crypt;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002537 const u8 *aad[5];
2538 size_t aad_len[5];
2539
2540 if (!sm || !sm->PTK_valid) {
2541 wpa_printf(MSG_DEBUG,
2542 "FILS: No KEK to decrypt Assocication Request frame");
2543 return -1;
2544 }
2545
2546 if (!wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
2547 wpa_printf(MSG_DEBUG,
2548 "FILS: Not a FILS AKM - reject association");
2549 return -1;
2550 }
2551
2552 end = ((const u8 *) mgmt) + frame_len;
2553 fc = le_to_host16(mgmt->frame_control);
2554 stype = WLAN_FC_GET_STYPE(fc);
2555 if (stype == WLAN_FC_STYPE_REASSOC_REQ)
2556 ie_start = mgmt->u.reassoc_req.variable;
2557 else
2558 ie_start = mgmt->u.assoc_req.variable;
2559 ie = ie_start;
2560
2561 /*
2562 * Find FILS Session element which is the last unencrypted element in
2563 * the frame.
2564 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002565 session = wpa_fils_validate_fils_session(sm, ie, end - ie,
2566 fils_session);
2567 if (!session) {
2568 wpa_printf(MSG_DEBUG, "FILS: Session validation failed");
2569 return -1;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002570 }
2571
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002572 crypt = session + 2 + session[1];
2573
2574 if (end - crypt < AES_BLOCK_SIZE) {
2575 wpa_printf(MSG_DEBUG,
2576 "FILS: Too short frame to include AES-SIV data");
2577 return -1;
2578 }
2579
2580 /* AES-SIV AAD vectors */
2581
2582 /* The STA's MAC address */
2583 aad[0] = mgmt->sa;
2584 aad_len[0] = ETH_ALEN;
2585 /* The AP's BSSID */
2586 aad[1] = mgmt->da;
2587 aad_len[1] = ETH_ALEN;
2588 /* The STA's nonce */
2589 aad[2] = sm->SNonce;
2590 aad_len[2] = FILS_NONCE_LEN;
2591 /* The AP's nonce */
2592 aad[3] = sm->ANonce;
2593 aad_len[3] = FILS_NONCE_LEN;
2594 /*
2595 * The (Re)Association Request frame from the Capability Information
2596 * field to the FILS Session element (both inclusive).
2597 */
2598 aad[4] = (const u8 *) &mgmt->u.assoc_req.capab_info;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002599 aad_len[4] = crypt - aad[4];
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002600
2601 if (aes_siv_decrypt(sm->PTK.kek, sm->PTK.kek_len, crypt, end - crypt,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002602 5, aad, aad_len, pos + (crypt - ie_start)) < 0) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002603 wpa_printf(MSG_DEBUG,
2604 "FILS: Invalid AES-SIV data in the frame");
2605 return -1;
2606 }
2607 wpa_hexdump(MSG_DEBUG, "FILS: Decrypted Association Request elements",
2608 pos, left - AES_BLOCK_SIZE);
2609
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002610 if (wpa_fils_validate_key_confirm(sm, pos, left - AES_BLOCK_SIZE) < 0) {
2611 wpa_printf(MSG_DEBUG, "FILS: Key Confirm validation failed");
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002612 return -1;
2613 }
2614
2615 return left - AES_BLOCK_SIZE;
2616}
2617
2618
2619int fils_encrypt_assoc(struct wpa_state_machine *sm, u8 *buf,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002620 size_t current_len, size_t max_len,
2621 const struct wpabuf *hlp)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002622{
2623 u8 *end = buf + max_len;
2624 u8 *pos = buf + current_len;
2625 struct ieee80211_mgmt *mgmt;
2626 struct wpabuf *plain;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002627 const u8 *aad[5];
2628 size_t aad_len[5];
2629
2630 if (!sm || !sm->PTK_valid)
2631 return -1;
2632
2633 wpa_hexdump(MSG_DEBUG,
2634 "FILS: Association Response frame before FILS processing",
2635 buf, current_len);
2636
2637 mgmt = (struct ieee80211_mgmt *) buf;
2638
2639 /* AES-SIV AAD vectors */
2640
2641 /* The AP's BSSID */
2642 aad[0] = mgmt->sa;
2643 aad_len[0] = ETH_ALEN;
2644 /* The STA's MAC address */
2645 aad[1] = mgmt->da;
2646 aad_len[1] = ETH_ALEN;
2647 /* The AP's nonce */
2648 aad[2] = sm->ANonce;
2649 aad_len[2] = FILS_NONCE_LEN;
2650 /* The STA's nonce */
2651 aad[3] = sm->SNonce;
2652 aad_len[3] = FILS_NONCE_LEN;
2653 /*
2654 * The (Re)Association Response frame from the Capability Information
2655 * field (the same offset in both Association and Reassociation
2656 * Response frames) to the FILS Session element (both inclusive).
2657 */
2658 aad[4] = (const u8 *) &mgmt->u.assoc_resp.capab_info;
2659 aad_len[4] = pos - aad[4];
2660
2661 /* The following elements will be encrypted with AES-SIV */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002662 plain = fils_prepare_plainbuf(sm, hlp);
2663 if (!plain) {
2664 wpa_printf(MSG_DEBUG, "FILS: Plain buffer prep failed");
2665 return -1;
2666 }
2667
2668 if (pos + wpabuf_len(plain) + AES_BLOCK_SIZE > end) {
2669 wpa_printf(MSG_DEBUG,
2670 "FILS: Not enough room for FILS elements");
Hai Shalom81f62d82019-07-22 12:10:00 -07002671 wpabuf_clear_free(plain);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002672 return -1;
2673 }
2674
2675 wpa_hexdump_buf_key(MSG_DEBUG, "FILS: Association Response plaintext",
2676 plain);
2677
2678 if (aes_siv_encrypt(sm->PTK.kek, sm->PTK.kek_len,
2679 wpabuf_head(plain), wpabuf_len(plain),
2680 5, aad, aad_len, pos) < 0) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002681 wpabuf_clear_free(plain);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002682 return -1;
2683 }
2684
2685 wpa_hexdump(MSG_DEBUG,
2686 "FILS: Encrypted Association Response elements",
2687 pos, AES_BLOCK_SIZE + wpabuf_len(plain));
2688 current_len += wpabuf_len(plain) + AES_BLOCK_SIZE;
Hai Shalom81f62d82019-07-22 12:10:00 -07002689 wpabuf_clear_free(plain);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002690
2691 sm->fils_completed = 1;
2692
2693 return current_len;
2694}
2695
2696
2697static struct wpabuf * fils_prepare_plainbuf(struct wpa_state_machine *sm,
2698 const struct wpabuf *hlp)
2699{
2700 struct wpabuf *plain;
2701 u8 *len, *tmp, *tmp2;
2702 u8 hdr[2];
2703 u8 *gtk, dummy_gtk[32];
2704 size_t gtk_len;
2705 struct wpa_group *gsm;
Hai Shalomfdcde762020-04-02 11:19:20 -07002706 size_t plain_len;
2707 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002708
Hai Shalomfdcde762020-04-02 11:19:20 -07002709 plain_len = 1000 + ieee80211w_kde_len(sm);
2710 if (conf->transition_disable)
2711 plain_len += 2 + RSN_SELECTOR_LEN + 1;
2712 plain = wpabuf_alloc(plain_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002713 if (!plain)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002714 return NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002715
2716 /* TODO: FILS Public Key */
2717
2718 /* FILS Key Confirmation */
2719 wpabuf_put_u8(plain, WLAN_EID_EXTENSION); /* Element ID */
2720 wpabuf_put_u8(plain, 1 + sm->fils_key_auth_len); /* Length */
2721 /* Element ID Extension */
2722 wpabuf_put_u8(plain, WLAN_EID_EXT_FILS_KEY_CONFIRM);
2723 wpabuf_put_data(plain, sm->fils_key_auth_ap, sm->fils_key_auth_len);
2724
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002725 /* FILS HLP Container */
2726 if (hlp)
2727 wpabuf_put_buf(plain, hlp);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002728
2729 /* TODO: FILS IP Address Assignment */
2730
2731 /* Key Delivery */
2732 gsm = sm->group;
2733 wpabuf_put_u8(plain, WLAN_EID_EXTENSION); /* Element ID */
2734 len = wpabuf_put(plain, 1);
2735 wpabuf_put_u8(plain, WLAN_EID_EXT_KEY_DELIVERY);
2736 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN,
2737 wpabuf_put(plain, WPA_KEY_RSC_LEN));
2738 /* GTK KDE */
2739 gtk = gsm->GTK[gsm->GN - 1];
2740 gtk_len = gsm->GTK_len;
Hai Shalomfdcde762020-04-02 11:19:20 -07002741 if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002742 /*
2743 * Provide unique random GTK to each STA to prevent use
2744 * of GTK in the BSS.
2745 */
2746 if (random_get_bytes(dummy_gtk, gtk_len) < 0) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002747 wpabuf_clear_free(plain);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002748 return NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002749 }
2750 gtk = dummy_gtk;
2751 }
2752 hdr[0] = gsm->GN & 0x03;
2753 hdr[1] = 0;
2754 tmp = wpabuf_put(plain, 0);
2755 tmp2 = wpa_add_kde(tmp, RSN_KEY_DATA_GROUPKEY, hdr, 2,
2756 gtk, gtk_len);
2757 wpabuf_put(plain, tmp2 - tmp);
2758
Hai Shalomfdcde762020-04-02 11:19:20 -07002759 /* IGTK KDE and BIGTK KDE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002760 tmp = wpabuf_put(plain, 0);
2761 tmp2 = ieee80211w_kde_add(sm, tmp);
2762 wpabuf_put(plain, tmp2 - tmp);
2763
Hai Shalomfdcde762020-04-02 11:19:20 -07002764 if (conf->transition_disable) {
2765 tmp = wpabuf_put(plain, 0);
2766 tmp2 = wpa_add_kde(tmp, WFA_KEY_DATA_TRANSITION_DISABLE,
2767 &conf->transition_disable, 1, NULL, 0);
2768 wpabuf_put(plain, tmp2 - tmp);
2769 }
2770
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002771 *len = (u8 *) wpabuf_put(plain, 0) - len - 1;
Hai Shalom74f70d42019-02-11 14:42:39 -08002772
2773#ifdef CONFIG_OCV
2774 if (wpa_auth_uses_ocv(sm)) {
2775 struct wpa_channel_info ci;
2776 u8 *pos;
2777
2778 if (wpa_channel_info(sm->wpa_auth, &ci) != 0) {
2779 wpa_printf(MSG_WARNING,
2780 "FILS: Failed to get channel info for OCI element");
Hai Shalom81f62d82019-07-22 12:10:00 -07002781 wpabuf_clear_free(plain);
Hai Shalom74f70d42019-02-11 14:42:39 -08002782 return NULL;
2783 }
Hai Shalom899fcc72020-10-19 14:38:18 -07002784#ifdef CONFIG_TESTING_OPTIONS
2785 if (conf->oci_freq_override_fils_assoc) {
2786 wpa_printf(MSG_INFO,
2787 "TEST: Override OCI frequency %d -> %u MHz",
2788 ci.frequency,
2789 conf->oci_freq_override_fils_assoc);
2790 ci.frequency = conf->oci_freq_override_fils_assoc;
2791 }
2792#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom74f70d42019-02-11 14:42:39 -08002793
2794 pos = wpabuf_put(plain, OCV_OCI_EXTENDED_LEN);
2795 if (ocv_insert_extended_oci(&ci, pos) < 0) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002796 wpabuf_clear_free(plain);
Hai Shalom74f70d42019-02-11 14:42:39 -08002797 return NULL;
2798 }
2799 }
2800#endif /* CONFIG_OCV */
2801
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002802 return plain;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002803}
2804
2805
2806int fils_set_tk(struct wpa_state_machine *sm)
2807{
2808 enum wpa_alg alg;
2809 int klen;
2810
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002811 if (!sm || !sm->PTK_valid) {
2812 wpa_printf(MSG_DEBUG, "FILS: No valid PTK available to set TK");
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002813 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002814 }
2815 if (sm->tk_already_set) {
2816 wpa_printf(MSG_DEBUG, "FILS: TK already set to the driver");
2817 return -1;
2818 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002819
2820 alg = wpa_cipher_to_alg(sm->pairwise);
2821 klen = wpa_cipher_key_len(sm->pairwise);
2822
2823 wpa_printf(MSG_DEBUG, "FILS: Configure TK to the driver");
2824 if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0,
Hai Shalomfdcde762020-04-02 11:19:20 -07002825 sm->PTK.tk, klen, KEY_FLAG_PAIRWISE_RX_TX)) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002826 wpa_printf(MSG_DEBUG, "FILS: Failed to set TK to the driver");
2827 return -1;
2828 }
Hai Shalome21d4e82020-04-29 16:34:06 -07002829 sm->tk_already_set = true;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002830
2831 return 0;
2832}
2833
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002834
2835u8 * hostapd_eid_assoc_fils_session(struct wpa_state_machine *sm, u8 *buf,
2836 const u8 *fils_session, struct wpabuf *hlp)
2837{
2838 struct wpabuf *plain;
2839 u8 *pos = buf;
2840
2841 /* FILS Session */
2842 *pos++ = WLAN_EID_EXTENSION; /* Element ID */
2843 *pos++ = 1 + FILS_SESSION_LEN; /* Length */
2844 *pos++ = WLAN_EID_EXT_FILS_SESSION; /* Element ID Extension */
2845 os_memcpy(pos, fils_session, FILS_SESSION_LEN);
2846 pos += FILS_SESSION_LEN;
2847
2848 plain = fils_prepare_plainbuf(sm, hlp);
2849 if (!plain) {
2850 wpa_printf(MSG_DEBUG, "FILS: Plain buffer prep failed");
2851 return NULL;
2852 }
2853
2854 os_memcpy(pos, wpabuf_head(plain), wpabuf_len(plain));
2855 pos += wpabuf_len(plain);
2856
Hai Shalomfdcde762020-04-02 11:19:20 -07002857 wpa_printf(MSG_DEBUG, "%s: plain buf_len: %zu", __func__,
2858 wpabuf_len(plain));
Hai Shalom81f62d82019-07-22 12:10:00 -07002859 wpabuf_clear_free(plain);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002860 sm->fils_completed = 1;
2861 return pos;
2862}
2863
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002864#endif /* CONFIG_FILS */
2865
2866
Hai Shalom74f70d42019-02-11 14:42:39 -08002867#ifdef CONFIG_OCV
2868int get_sta_tx_parameters(struct wpa_state_machine *sm, int ap_max_chanwidth,
2869 int ap_seg1_idx, int *bandwidth, int *seg1_idx)
2870{
2871 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
2872
2873 if (!wpa_auth->cb->get_sta_tx_params)
2874 return -1;
2875 return wpa_auth->cb->get_sta_tx_params(wpa_auth->cb_ctx, sm->addr,
2876 ap_max_chanwidth, ap_seg1_idx,
2877 bandwidth, seg1_idx);
2878}
2879#endif /* CONFIG_OCV */
2880
2881
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002882SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
2883{
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002884 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002885 struct wpa_ptk PTK;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07002886 int ok = 0, psk_found = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002887 const u8 *pmk = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002888 size_t pmk_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002889 int ft;
2890 const u8 *eapol_key_ie, *key_data, *mic;
2891 u16 key_data_length;
2892 size_t mic_len, eapol_key_ie_len;
2893 struct ieee802_1x_hdr *hdr;
2894 struct wpa_eapol_key *key;
2895 struct wpa_eapol_ie_parse kde;
Hai Shalom021b0b52019-04-10 11:17:58 -07002896 int vlan_id = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07002897 int owe_ptk_workaround = !!wpa_auth->conf.owe_ptk_workaround;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002898
2899 SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07002900 sm->EAPOLKeyReceived = false;
2901 sm->update_snonce = false;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002902 os_memset(&PTK, 0, sizeof(PTK));
2903
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002904 mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002905
2906 /* WPA with IEEE 802.1X: use the derived PMK from EAP
2907 * WPA-PSK: iterate through possible PSKs and select the one matching
2908 * the packet */
2909 for (;;) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002910 if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
2911 !wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002912 pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr,
Hai Shalom021b0b52019-04-10 11:17:58 -07002913 sm->p2p_dev_addr, pmk, &pmk_len,
2914 &vlan_id);
Hai Shalomfdcde762020-04-02 11:19:20 -07002915 if (!pmk)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002916 break;
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07002917 psk_found = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002918#ifdef CONFIG_IEEE80211R_AP
2919 if (wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) {
2920 os_memcpy(sm->xxkey, pmk, pmk_len);
2921 sm->xxkey_len = pmk_len;
2922 }
2923#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002924 } else {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002925 pmk = sm->PMK;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002926 pmk_len = sm->pmk_len;
2927 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002928
Hai Shalom81f62d82019-07-22 12:10:00 -07002929 if ((!pmk || !pmk_len) && sm->pmksa) {
2930 wpa_printf(MSG_DEBUG, "WPA: Use PMK from PMKSA cache");
2931 pmk = sm->pmksa->pmk;
2932 pmk_len = sm->pmksa->pmk_len;
2933 }
2934
Hai Shalomfdcde762020-04-02 11:19:20 -07002935 if (wpa_derive_ptk(sm, sm->SNonce, pmk, pmk_len, &PTK,
2936 owe_ptk_workaround == 2) < 0)
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002937 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002938
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002939 if (mic_len &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002940 wpa_verify_key_mic(sm->wpa_key_mgmt, pmk_len, &PTK,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002941 sm->last_rx_eapol_key,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002942 sm->last_rx_eapol_key_len) == 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -07002943 if (sm->PMK != pmk) {
2944 os_memcpy(sm->PMK, pmk, pmk_len);
2945 sm->pmk_len = pmk_len;
2946 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002947 ok = 1;
2948 break;
2949 }
2950
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002951#ifdef CONFIG_FILS
2952 if (!mic_len &&
2953 wpa_aead_decrypt(sm, &PTK, sm->last_rx_eapol_key,
2954 sm->last_rx_eapol_key_len, NULL) == 0) {
2955 ok = 1;
2956 break;
2957 }
2958#endif /* CONFIG_FILS */
2959
Hai Shalomfdcde762020-04-02 11:19:20 -07002960#ifdef CONFIG_OWE
2961 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE && pmk_len > 32 &&
2962 owe_ptk_workaround == 1) {
2963 wpa_printf(MSG_DEBUG,
2964 "OWE: Try PTK derivation workaround with SHA256");
2965 owe_ptk_workaround = 2;
2966 continue;
2967 }
2968#endif /* CONFIG_OWE */
2969
Roshan Pius3a1667e2018-07-03 15:17:14 -07002970 if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
2971 wpa_key_mgmt_sae(sm->wpa_key_mgmt))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002972 break;
2973 }
2974
2975 if (!ok) {
2976 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
2977 "invalid MIC in msg 2/4 of 4-Way Handshake");
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07002978 if (psk_found)
2979 wpa_auth_psk_failure_report(sm->wpa_auth, sm->addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002980 return;
2981 }
2982
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002983 /*
2984 * Note: last_rx_eapol_key length fields have already been validated in
2985 * wpa_receive().
2986 */
2987 hdr = (struct ieee802_1x_hdr *) sm->last_rx_eapol_key;
2988 key = (struct wpa_eapol_key *) (hdr + 1);
2989 mic = (u8 *) (key + 1);
2990 key_data = mic + mic_len + 2;
2991 key_data_length = WPA_GET_BE16(mic + mic_len);
2992 if (key_data_length > sm->last_rx_eapol_key_len - sizeof(*hdr) -
2993 sizeof(*key) - mic_len - 2)
2994 return;
2995
2996 if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) {
2997 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
2998 "received EAPOL-Key msg 2/4 with invalid Key Data contents");
2999 return;
3000 }
3001 if (kde.rsn_ie) {
3002 eapol_key_ie = kde.rsn_ie;
3003 eapol_key_ie_len = kde.rsn_ie_len;
3004 } else if (kde.osen) {
3005 eapol_key_ie = kde.osen;
3006 eapol_key_ie_len = kde.osen_len;
3007 } else {
3008 eapol_key_ie = kde.wpa_ie;
3009 eapol_key_ie_len = kde.wpa_ie_len;
3010 }
3011 ft = sm->wpa == WPA_VERSION_WPA2 && wpa_key_mgmt_ft(sm->wpa_key_mgmt);
Hai Shalomfdcde762020-04-02 11:19:20 -07003012 if (!sm->wpa_ie ||
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003013 wpa_compare_rsn_ie(ft, sm->wpa_ie, sm->wpa_ie_len,
3014 eapol_key_ie, eapol_key_ie_len)) {
3015 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
3016 "WPA IE from (Re)AssocReq did not match with msg 2/4");
3017 if (sm->wpa_ie) {
3018 wpa_hexdump(MSG_DEBUG, "WPA IE in AssocReq",
3019 sm->wpa_ie, sm->wpa_ie_len);
3020 }
3021 wpa_hexdump(MSG_DEBUG, "WPA IE in msg 2/4",
3022 eapol_key_ie, eapol_key_ie_len);
3023 /* MLME-DEAUTHENTICATE.request */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003024 wpa_sta_disconnect(wpa_auth, sm->addr,
3025 WLAN_REASON_PREV_AUTH_NOT_VALID);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003026 return;
3027 }
Hai Shalomc3565922019-10-28 11:58:20 -07003028 if ((!sm->rsnxe && kde.rsnxe) ||
3029 (sm->rsnxe && !kde.rsnxe) ||
3030 (sm->rsnxe && kde.rsnxe &&
3031 (sm->rsnxe_len != kde.rsnxe_len ||
3032 os_memcmp(sm->rsnxe, kde.rsnxe, sm->rsnxe_len) != 0))) {
3033 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
3034 "RSNXE from (Re)AssocReq did not match the one in EAPOL-Key msg 2/4");
3035 wpa_hexdump(MSG_DEBUG, "RSNXE in AssocReq",
3036 sm->rsnxe, sm->rsnxe_len);
3037 wpa_hexdump(MSG_DEBUG, "RSNXE in EAPOL-Key msg 2/4",
3038 kde.rsnxe, kde.rsnxe_len);
3039 /* MLME-DEAUTHENTICATE.request */
3040 wpa_sta_disconnect(wpa_auth, sm->addr,
3041 WLAN_REASON_PREV_AUTH_NOT_VALID);
3042 return;
3043 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003044#ifdef CONFIG_OCV
3045 if (wpa_auth_uses_ocv(sm)) {
3046 struct wpa_channel_info ci;
3047 int tx_chanwidth;
3048 int tx_seg1_idx;
Hai Shalom899fcc72020-10-19 14:38:18 -07003049 enum oci_verify_result res;
Hai Shalom74f70d42019-02-11 14:42:39 -08003050
3051 if (wpa_channel_info(wpa_auth, &ci) != 0) {
3052 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
3053 "Failed to get channel info to validate received OCI in EAPOL-Key 2/4");
3054 return;
3055 }
3056
3057 if (get_sta_tx_parameters(sm,
3058 channel_width_to_int(ci.chanwidth),
3059 ci.seg1_idx, &tx_chanwidth,
3060 &tx_seg1_idx) < 0)
3061 return;
3062
Hai Shalom899fcc72020-10-19 14:38:18 -07003063 res = ocv_verify_tx_params(kde.oci, kde.oci_len, &ci,
3064 tx_chanwidth, tx_seg1_idx);
3065 if (wpa_auth_uses_ocv(sm) == 2 && res == OCI_NOT_FOUND) {
3066 /* Work around misbehaving STAs */
3067 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
3068 "Disable OCV with a STA that does not send OCI");
3069 wpa_auth_set_ocv(sm, 0);
3070 } else if (res != OCI_SUCCESS) {
3071 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
3072 "OCV failed: %s", ocv_errorstr);
3073 if (wpa_auth->conf.msg_ctx)
3074 wpa_msg(wpa_auth->conf.msg_ctx, MSG_INFO,
3075 OCV_FAILURE "addr=" MACSTR
3076 " frame=eapol-key-m2 error=%s",
3077 MAC2STR(sm->addr), ocv_errorstr);
Hai Shalom74f70d42019-02-11 14:42:39 -08003078 return;
3079 }
3080 }
3081#endif /* CONFIG_OCV */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003082#ifdef CONFIG_IEEE80211R_AP
3083 if (ft && ft_check_msg_2_of_4(wpa_auth, sm, &kde) < 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003084 wpa_sta_disconnect(wpa_auth, sm->addr,
3085 WLAN_REASON_PREV_AUTH_NOT_VALID);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003086 return;
3087 }
3088#endif /* CONFIG_IEEE80211R_AP */
3089#ifdef CONFIG_P2P
3090 if (kde.ip_addr_req && kde.ip_addr_req[0] &&
3091 wpa_auth->ip_pool && WPA_GET_BE32(sm->ip_addr) == 0) {
3092 int idx;
3093 wpa_printf(MSG_DEBUG,
3094 "P2P: IP address requested in EAPOL-Key exchange");
3095 idx = bitfield_get_first_zero(wpa_auth->ip_pool);
3096 if (idx >= 0) {
3097 u32 start = WPA_GET_BE32(wpa_auth->conf.ip_addr_start);
3098 bitfield_set(wpa_auth->ip_pool, idx);
3099 WPA_PUT_BE32(sm->ip_addr, start + idx);
3100 wpa_printf(MSG_DEBUG,
3101 "P2P: Assigned IP address %u.%u.%u.%u to "
3102 MACSTR, sm->ip_addr[0], sm->ip_addr[1],
3103 sm->ip_addr[2], sm->ip_addr[3],
3104 MAC2STR(sm->addr));
3105 }
3106 }
3107#endif /* CONFIG_P2P */
3108
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003109#ifdef CONFIG_DPP2
3110 if (DPP_VERSION > 1 && kde.dpp_kde) {
3111 wpa_printf(MSG_DEBUG,
3112 "DPP: peer Protocol Version %u Flags 0x%x",
3113 kde.dpp_kde[0], kde.dpp_kde[1]);
3114 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP &&
3115 wpa_auth->conf.dpp_pfs != 2 &&
3116 (kde.dpp_kde[1] & DPP_KDE_PFS_ALLOWED) &&
3117 !sm->dpp_z) {
3118 wpa_printf(MSG_INFO,
3119 "DPP: Peer indicated it supports PFS and local configuration allows this, but PFS was not negotiated for the association");
3120 wpa_sta_disconnect(wpa_auth, sm->addr,
3121 WLAN_REASON_PREV_AUTH_NOT_VALID);
3122 return;
3123 }
3124 }
3125#endif /* CONFIG_DPP2 */
3126
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003127#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003128 if (sm->wpa == WPA_VERSION_WPA2 && wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
3129 /*
3130 * Verify that PMKR1Name from EAPOL-Key message 2/4 matches
3131 * with the value we derived.
3132 */
Dmitry Shmidtc2817022014-07-02 10:32:10 -07003133 if (os_memcmp_const(sm->sup_pmk_r1_name, sm->pmk_r1_name,
3134 WPA_PMK_NAME_LEN) != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003135 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07003136 "PMKR1Name mismatch in FT 4-way handshake");
3137 wpa_hexdump(MSG_DEBUG,
3138 "FT: PMKR1Name from Supplicant",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003139 sm->sup_pmk_r1_name, WPA_PMK_NAME_LEN);
3140 wpa_hexdump(MSG_DEBUG, "FT: Derived PMKR1Name",
3141 sm->pmk_r1_name, WPA_PMK_NAME_LEN);
3142 return;
3143 }
3144 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003145#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003146
Hai Shalom021b0b52019-04-10 11:17:58 -07003147 if (vlan_id && wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
3148 wpa_auth_update_vlan(wpa_auth, sm->addr, vlan_id) < 0) {
3149 wpa_sta_disconnect(wpa_auth, sm->addr,
3150 WLAN_REASON_PREV_AUTH_NOT_VALID);
3151 return;
3152 }
3153
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003154 sm->pending_1_of_4_timeout = 0;
3155 eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm);
3156
3157 if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) {
3158 /* PSK may have changed from the previous choice, so update
3159 * state machine data based on whatever PSK was selected here.
3160 */
3161 os_memcpy(sm->PMK, pmk, PMK_LEN);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003162 sm->pmk_len = PMK_LEN;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003163 }
3164
Hai Shalome21d4e82020-04-29 16:34:06 -07003165 sm->MICVerified = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003166
3167 os_memcpy(&sm->PTK, &PTK, sizeof(PTK));
Hai Shalom81f62d82019-07-22 12:10:00 -07003168 forced_memzero(&PTK, sizeof(PTK));
Hai Shalome21d4e82020-04-29 16:34:06 -07003169 sm->PTK_valid = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003170}
3171
3172
3173SM_STATE(WPA_PTK, PTKCALCNEGOTIATING2)
3174{
3175 SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING2, wpa_ptk);
3176 sm->TimeoutCtr = 0;
3177}
3178
3179
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003180static int ieee80211w_kde_len(struct wpa_state_machine *sm)
3181{
Hai Shalomfdcde762020-04-02 11:19:20 -07003182 size_t len = 0;
3183
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003184 if (sm->mgmt_frame_prot) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003185 len += 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN;
3186 len += wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
3187 }
3188 if (sm->mgmt_frame_prot && sm->wpa_auth->conf.beacon_prot) {
3189 len += 2 + RSN_SELECTOR_LEN + WPA_BIGTK_KDE_PREFIX_LEN;
3190 len += wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003191 }
3192
Hai Shalomfdcde762020-04-02 11:19:20 -07003193 return len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003194}
3195
3196
3197static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos)
3198{
3199 struct wpa_igtk_kde igtk;
Hai Shalomfdcde762020-04-02 11:19:20 -07003200 struct wpa_bigtk_kde bigtk;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003201 struct wpa_group *gsm = sm->group;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003202 u8 rsc[WPA_KEY_RSC_LEN];
Hai Shalomfdcde762020-04-02 11:19:20 -07003203 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
3204 size_t len = wpa_cipher_key_len(conf->group_mgmt_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003205
3206 if (!sm->mgmt_frame_prot)
3207 return pos;
3208
3209 igtk.keyid[0] = gsm->GN_igtk;
3210 igtk.keyid[1] = 0;
3211 if (gsm->wpa_group_state != WPA_GROUP_SETKEYSDONE ||
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003212 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, rsc) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003213 os_memset(igtk.pn, 0, sizeof(igtk.pn));
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003214 else
3215 os_memcpy(igtk.pn, rsc, sizeof(igtk.pn));
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003216 os_memcpy(igtk.igtk, gsm->IGTK[gsm->GN_igtk - 4], len);
Hai Shalomfdcde762020-04-02 11:19:20 -07003217 if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003218 /*
3219 * Provide unique random IGTK to each STA to prevent use of
3220 * IGTK in the BSS.
3221 */
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003222 if (random_get_bytes(igtk.igtk, len) < 0)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003223 return pos;
3224 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003225 pos = wpa_add_kde(pos, RSN_KEY_DATA_IGTK,
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003226 (const u8 *) &igtk, WPA_IGTK_KDE_PREFIX_LEN + len,
3227 NULL, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003228
Hai Shalomfdcde762020-04-02 11:19:20 -07003229 if (!conf->beacon_prot)
3230 return pos;
3231
3232 bigtk.keyid[0] = gsm->GN_bigtk;
3233 bigtk.keyid[1] = 0;
3234 if (gsm->wpa_group_state != WPA_GROUP_SETKEYSDONE ||
3235 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_bigtk, rsc) < 0)
3236 os_memset(bigtk.pn, 0, sizeof(bigtk.pn));
3237 else
3238 os_memcpy(bigtk.pn, rsc, sizeof(bigtk.pn));
3239 os_memcpy(bigtk.bigtk, gsm->BIGTK[gsm->GN_bigtk - 6], len);
Hai Shalom899fcc72020-10-19 14:38:18 -07003240 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
3241 /*
3242 * Provide unique random BIGTK to each OSEN STA to prevent use
3243 * of BIGTK in the BSS.
3244 */
3245 if (random_get_bytes(bigtk.bigtk, len) < 0)
3246 return pos;
3247 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003248 pos = wpa_add_kde(pos, RSN_KEY_DATA_BIGTK,
3249 (const u8 *) &bigtk, WPA_BIGTK_KDE_PREFIX_LEN + len,
3250 NULL, 0);
3251
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003252 return pos;
3253}
3254
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003255
Hai Shalom74f70d42019-02-11 14:42:39 -08003256static int ocv_oci_len(struct wpa_state_machine *sm)
3257{
3258#ifdef CONFIG_OCV
3259 if (wpa_auth_uses_ocv(sm))
3260 return OCV_OCI_KDE_LEN;
3261#endif /* CONFIG_OCV */
3262 return 0;
3263}
3264
Hai Shalom899fcc72020-10-19 14:38:18 -07003265
3266static int ocv_oci_add(struct wpa_state_machine *sm, u8 **argpos,
3267 unsigned int freq)
Hai Shalom74f70d42019-02-11 14:42:39 -08003268{
3269#ifdef CONFIG_OCV
3270 struct wpa_channel_info ci;
3271
3272 if (!wpa_auth_uses_ocv(sm))
3273 return 0;
3274
3275 if (wpa_channel_info(sm->wpa_auth, &ci) != 0) {
3276 wpa_printf(MSG_WARNING,
3277 "Failed to get channel info for OCI element");
3278 return -1;
3279 }
Hai Shalom899fcc72020-10-19 14:38:18 -07003280#ifdef CONFIG_TESTING_OPTIONS
3281 if (freq) {
3282 wpa_printf(MSG_INFO,
3283 "TEST: Override OCI KDE frequency %d -> %u MHz",
3284 ci.frequency, freq);
3285 ci.frequency = freq;
3286 }
3287#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom74f70d42019-02-11 14:42:39 -08003288
3289 return ocv_insert_oci_kde(&ci, argpos);
3290#else /* CONFIG_OCV */
3291 return 0;
3292#endif /* CONFIG_OCV */
3293}
3294
3295
Hai Shalomfdcde762020-04-02 11:19:20 -07003296#ifdef CONFIG_TESTING_OPTIONS
3297static u8 * replace_ie(const char *name, const u8 *old_buf, size_t *len, u8 eid,
3298 const u8 *ie, size_t ie_len)
3299{
3300 const u8 *elem;
3301 u8 *buf;
3302
3303 wpa_printf(MSG_DEBUG, "TESTING: %s EAPOL override", name);
3304 wpa_hexdump(MSG_DEBUG, "TESTING: wpa_ie before override",
3305 old_buf, *len);
3306 buf = os_malloc(*len + ie_len);
3307 if (!buf)
3308 return NULL;
3309 os_memcpy(buf, old_buf, *len);
3310 elem = get_ie(buf, *len, eid);
3311 if (elem) {
3312 u8 elem_len = 2 + elem[1];
3313
3314 os_memmove((void *) elem, elem + elem_len,
3315 *len - (elem - buf) - elem_len);
3316 *len -= elem_len;
3317 }
3318 os_memcpy(buf + *len, ie, ie_len);
3319 *len += ie_len;
3320 wpa_hexdump(MSG_DEBUG, "TESTING: wpa_ie after EAPOL override",
3321 buf, *len);
3322
3323 return buf;
3324}
3325#endif /* CONFIG_TESTING_OPTIONS */
3326
3327
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003328SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
3329{
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003330 u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde = NULL, *pos, dummy_gtk[32];
Hai Shalomfdcde762020-04-02 11:19:20 -07003331 size_t gtk_len, kde_len, wpa_ie_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003332 struct wpa_group *gsm = sm->group;
3333 u8 *wpa_ie;
Hai Shalomfdcde762020-04-02 11:19:20 -07003334 int secure, gtkidx, encr = 0;
3335 u8 *wpa_ie_buf = NULL, *wpa_ie_buf2 = NULL;
3336 u8 hdr[2];
3337 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003338
3339 SM_ENTRY_MA(WPA_PTK, PTKINITNEGOTIATING, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07003340 sm->TimeoutEvt = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003341
3342 sm->TimeoutCtr++;
Hai Shalomfdcde762020-04-02 11:19:20 -07003343 if (conf->wpa_disable_eapol_key_retries && sm->TimeoutCtr > 1) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003344 /* Do not allow retransmission of EAPOL-Key msg 3/4 */
3345 return;
3346 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003347 if (sm->TimeoutCtr > conf->wpa_pairwise_update_count) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003348 /* No point in sending the EAPOL-Key - we will disconnect
3349 * immediately following this. */
3350 return;
3351 }
3352
3353 /* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, [MDIE],
Hai Shalomfdcde762020-04-02 11:19:20 -07003354 GTK[GN], IGTK, [BIGTK], [FTIE], [TIE * 2])
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003355 */
3356 os_memset(rsc, 0, WPA_KEY_RSC_LEN);
3357 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc);
3358 /* If FT is used, wpa_auth->wpa_ie includes both RSNIE and MDIE */
3359 wpa_ie = sm->wpa_auth->wpa_ie;
3360 wpa_ie_len = sm->wpa_auth->wpa_ie_len;
Hai Shalomfdcde762020-04-02 11:19:20 -07003361 if (sm->wpa == WPA_VERSION_WPA && (conf->wpa & WPA_PROTO_RSN) &&
3362 wpa_ie_len > wpa_ie[1] + 2U && wpa_ie[0] == WLAN_EID_RSN) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003363 /* WPA-only STA, remove RSN IE and possible MDIE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003364 wpa_ie = wpa_ie + wpa_ie[1] + 2;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003365 if (wpa_ie[0] == WLAN_EID_MOBILITY_DOMAIN)
3366 wpa_ie = wpa_ie + wpa_ie[1] + 2;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003367 wpa_ie_len = wpa_ie[1] + 2;
3368 }
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003369#ifdef CONFIG_TESTING_OPTIONS
Hai Shalomfdcde762020-04-02 11:19:20 -07003370 if (conf->rsne_override_eapol_set) {
3371 wpa_ie_buf2 = replace_ie(
3372 "RSNE", wpa_ie, &wpa_ie_len, WLAN_EID_RSN,
3373 conf->rsne_override_eapol,
3374 conf->rsne_override_eapol_len);
3375 if (!wpa_ie_buf2)
3376 goto done;
3377 wpa_ie = wpa_ie_buf2;
3378 }
3379 if (conf->rsnxe_override_eapol_set) {
3380 wpa_ie_buf = replace_ie(
3381 "RSNXE", wpa_ie, &wpa_ie_len, WLAN_EID_RSNX,
3382 conf->rsnxe_override_eapol,
3383 conf->rsnxe_override_eapol_len);
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003384 if (!wpa_ie_buf)
Hai Shalomfdcde762020-04-02 11:19:20 -07003385 goto done;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003386 wpa_ie = wpa_ie_buf;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003387 }
3388#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003389 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
3390 "sending 3/4 msg of 4-Way Handshake");
3391 if (sm->wpa == WPA_VERSION_WPA2) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003392 if (sm->use_ext_key_id && sm->TimeoutCtr == 1 &&
3393 wpa_auth_set_key(sm->wpa_auth, 0,
3394 wpa_cipher_to_alg(sm->pairwise),
3395 sm->addr,
3396 sm->keyidx_active, sm->PTK.tk,
3397 wpa_cipher_key_len(sm->pairwise),
3398 KEY_FLAG_PAIRWISE_RX)) {
3399 wpa_sta_disconnect(sm->wpa_auth, sm->addr,
3400 WLAN_REASON_PREV_AUTH_NOT_VALID);
3401 return;
3402 }
3403
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003404 /* WPA2 send GTK in the 4-way handshake */
3405 secure = 1;
3406 gtk = gsm->GTK[gsm->GN - 1];
3407 gtk_len = gsm->GTK_len;
Hai Shalomfdcde762020-04-02 11:19:20 -07003408 if (conf->disable_gtk ||
Roshan Pius3a1667e2018-07-03 15:17:14 -07003409 sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003410 /*
3411 * Provide unique random GTK to each STA to prevent use
3412 * of GTK in the BSS.
3413 */
3414 if (random_get_bytes(dummy_gtk, gtk_len) < 0)
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003415 goto done;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003416 gtk = dummy_gtk;
3417 }
Hai Shalomc3565922019-10-28 11:58:20 -07003418 gtkidx = gsm->GN;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003419 _rsc = rsc;
3420 encr = 1;
3421 } else {
3422 /* WPA does not include GTK in msg 3/4 */
3423 secure = 0;
3424 gtk = NULL;
3425 gtk_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003426 _rsc = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003427 if (sm->rx_eapol_key_secure) {
3428 /*
3429 * It looks like Windows 7 supplicant tries to use
3430 * Secure bit in msg 2/4 after having reported Michael
3431 * MIC failure and it then rejects the 4-way handshake
3432 * if msg 3/4 does not set Secure bit. Work around this
3433 * by setting the Secure bit here even in the case of
3434 * WPA if the supplicant used it first.
3435 */
3436 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07003437 "STA used Secure bit in WPA msg 2/4 - set Secure for 3/4 as workaround");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003438 secure = 1;
3439 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003440 }
3441
Hai Shalom74f70d42019-02-11 14:42:39 -08003442 kde_len = wpa_ie_len + ieee80211w_kde_len(sm) + ocv_oci_len(sm);
Hai Shalomfdcde762020-04-02 11:19:20 -07003443
3444 if (sm->use_ext_key_id)
3445 kde_len += 2 + RSN_SELECTOR_LEN + 2;
3446
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003447 if (gtk)
3448 kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003449#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003450 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
3451 kde_len += 2 + PMKID_LEN; /* PMKR1Name into RSN IE */
3452 kde_len += 300; /* FTIE + 2 * TIE */
3453 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003454#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08003455#ifdef CONFIG_P2P
3456 if (WPA_GET_BE32(sm->ip_addr) > 0)
3457 kde_len += 2 + RSN_SELECTOR_LEN + 3 * 4;
3458#endif /* CONFIG_P2P */
Hai Shalomfdcde762020-04-02 11:19:20 -07003459
3460 if (conf->transition_disable)
3461 kde_len += 2 + RSN_SELECTOR_LEN + 1;
3462
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003463#ifdef CONFIG_DPP2
3464 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP)
3465 kde_len += 2 + RSN_SELECTOR_LEN + 2;
3466#endif /* CONFIG_DPP2 */
3467
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003468 kde = os_malloc(kde_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07003469 if (!kde)
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003470 goto done;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003471
3472 pos = kde;
3473 os_memcpy(pos, wpa_ie, wpa_ie_len);
3474 pos += wpa_ie_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003475#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003476 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08003477 int res;
3478 size_t elen;
3479
3480 elen = pos - kde;
3481 res = wpa_insert_pmkid(kde, &elen, sm->pmk_r1_name);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003482 if (res < 0) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003483 wpa_printf(MSG_ERROR,
3484 "FT: Failed to insert PMKR1Name into RSN IE in EAPOL-Key data");
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003485 goto done;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003486 }
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08003487 pos -= wpa_ie_len;
3488 pos += elen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003489 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003490#endif /* CONFIG_IEEE80211R_AP */
Hai Shalomfdcde762020-04-02 11:19:20 -07003491 hdr[1] = 0;
3492
3493 if (sm->use_ext_key_id) {
3494 hdr[0] = sm->keyidx_active & 0x01;
3495 pos = wpa_add_kde(pos, RSN_KEY_DATA_KEYID, hdr, 2, NULL, 0);
3496 }
3497
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003498 if (gtk) {
Hai Shalomc3565922019-10-28 11:58:20 -07003499 hdr[0] = gtkidx & 0x03;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003500 pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
3501 gtk, gtk_len);
3502 }
3503 pos = ieee80211w_kde_add(sm, pos);
Hai Shalom899fcc72020-10-19 14:38:18 -07003504 if (ocv_oci_add(sm, &pos, conf->oci_freq_override_eapol_m3) < 0)
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003505 goto done;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003506
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003507#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003508 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
3509 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003510
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08003511 if (sm->assoc_resp_ftie &&
3512 kde + kde_len - pos >= 2 + sm->assoc_resp_ftie[1]) {
3513 os_memcpy(pos, sm->assoc_resp_ftie,
3514 2 + sm->assoc_resp_ftie[1]);
3515 res = 2 + sm->assoc_resp_ftie[1];
3516 } else {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003517 int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt);
3518
3519 res = wpa_write_ftie(conf, use_sha384,
3520 conf->r0_key_holder,
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08003521 conf->r0_key_holder_len,
3522 NULL, NULL, pos,
3523 kde + kde_len - pos,
Hai Shalomfdcde762020-04-02 11:19:20 -07003524 NULL, 0, 0);
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08003525 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003526 if (res < 0) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003527 wpa_printf(MSG_ERROR,
3528 "FT: Failed to insert FTIE into EAPOL-Key Key Data");
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003529 goto done;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003530 }
3531 pos += res;
3532
3533 /* TIE[ReassociationDeadline] (TU) */
3534 *pos++ = WLAN_EID_TIMEOUT_INTERVAL;
3535 *pos++ = 5;
3536 *pos++ = WLAN_TIMEOUT_REASSOC_DEADLINE;
3537 WPA_PUT_LE32(pos, conf->reassociation_deadline);
3538 pos += 4;
3539
3540 /* TIE[KeyLifetime] (seconds) */
3541 *pos++ = WLAN_EID_TIMEOUT_INTERVAL;
3542 *pos++ = 5;
3543 *pos++ = WLAN_TIMEOUT_KEY_LIFETIME;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003544 WPA_PUT_LE32(pos, conf->r0_key_lifetime);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003545 pos += 4;
3546 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003547#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08003548#ifdef CONFIG_P2P
3549 if (WPA_GET_BE32(sm->ip_addr) > 0) {
3550 u8 addr[3 * 4];
3551 os_memcpy(addr, sm->ip_addr, 4);
Hai Shalomfdcde762020-04-02 11:19:20 -07003552 os_memcpy(addr + 4, conf->ip_addr_mask, 4);
3553 os_memcpy(addr + 8, conf->ip_addr_go, 4);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08003554 pos = wpa_add_kde(pos, WFA_KEY_DATA_IP_ADDR_ALLOC,
3555 addr, sizeof(addr), NULL, 0);
3556 }
3557#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003558
Hai Shalomfdcde762020-04-02 11:19:20 -07003559 if (conf->transition_disable)
3560 pos = wpa_add_kde(pos, WFA_KEY_DATA_TRANSITION_DISABLE,
3561 &conf->transition_disable, 1, NULL, 0);
3562
Hai Shalom4fbc08f2020-05-18 12:37:00 -07003563#ifdef CONFIG_DPP2
3564 if (DPP_VERSION > 1 && sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP) {
3565 u8 payload[2];
3566
3567 payload[0] = DPP_VERSION; /* Protocol Version */
3568 payload[1] = 0; /* Flags */
3569 if (conf->dpp_pfs == 0)
3570 payload[1] |= DPP_KDE_PFS_ALLOWED;
3571 else if (conf->dpp_pfs == 1)
3572 payload[1] |= DPP_KDE_PFS_ALLOWED |
3573 DPP_KDE_PFS_REQUIRED;
3574 pos = wpa_add_kde(pos, WFA_KEY_DATA_DPP,
3575 payload, sizeof(payload), NULL, 0);
3576 }
3577#endif /* CONFIG_DPP2 */
3578
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003579 wpa_send_eapol(sm->wpa_auth, sm,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003580 (secure ? WPA_KEY_INFO_SECURE : 0) |
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003581 (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
3582 WPA_KEY_INFO_MIC : 0) |
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003583 WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL |
3584 WPA_KEY_INFO_KEY_TYPE,
Hai Shalomc3565922019-10-28 11:58:20 -07003585 _rsc, sm->ANonce, kde, pos - kde, 0, encr);
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003586done:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003587 os_free(kde);
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003588 os_free(wpa_ie_buf);
Hai Shalomfdcde762020-04-02 11:19:20 -07003589 os_free(wpa_ie_buf2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003590}
3591
3592
3593SM_STATE(WPA_PTK, PTKINITDONE)
3594{
3595 SM_ENTRY_MA(WPA_PTK, PTKINITDONE, wpa_ptk);
Hai Shalome21d4e82020-04-29 16:34:06 -07003596 sm->EAPOLKeyReceived = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003597 if (sm->Pair) {
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07003598 enum wpa_alg alg = wpa_cipher_to_alg(sm->pairwise);
3599 int klen = wpa_cipher_key_len(sm->pairwise);
Hai Shalomfdcde762020-04-02 11:19:20 -07003600 int res;
3601
3602 if (sm->use_ext_key_id)
3603 res = wpa_auth_set_key(sm->wpa_auth, 0, 0, sm->addr,
3604 sm->keyidx_active, NULL, 0,
3605 KEY_FLAG_PAIRWISE_RX_TX_MODIFY);
3606 else
3607 res = wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr,
3608 0, sm->PTK.tk, klen,
3609 KEY_FLAG_PAIRWISE_RX_TX);
3610 if (res) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003611 wpa_sta_disconnect(sm->wpa_auth, sm->addr,
3612 WLAN_REASON_PREV_AUTH_NOT_VALID);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003613 return;
3614 }
3615 /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */
Hai Shalome21d4e82020-04-29 16:34:06 -07003616 sm->pairwise_set = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003617
Hai Shalom81f62d82019-07-22 12:10:00 -07003618 wpa_auth_set_ptk_rekey_timer(sm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003619
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003620 if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
3621 sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP ||
3622 sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003623 wpa_auth_set_eapol(sm->wpa_auth, sm->addr,
3624 WPA_EAPOL_authorized, 1);
3625 }
3626 }
3627
3628 if (0 /* IBSS == TRUE */) {
3629 sm->keycount++;
3630 if (sm->keycount == 2) {
3631 wpa_auth_set_eapol(sm->wpa_auth, sm->addr,
3632 WPA_EAPOL_portValid, 1);
3633 }
3634 } else {
3635 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid,
3636 1);
3637 }
Hai Shalome21d4e82020-04-29 16:34:06 -07003638 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyAvailable,
3639 false);
3640 wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyDone, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003641 if (sm->wpa == WPA_VERSION_WPA)
Hai Shalome21d4e82020-04-29 16:34:06 -07003642 sm->PInitAKeys = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003643 else
Hai Shalome21d4e82020-04-29 16:34:06 -07003644 sm->has_GTK = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003645 wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO,
3646 "pairwise key handshake completed (%s)",
3647 sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN");
3648
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003649#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003650 wpa_ft_push_pmk_r1(sm->wpa_auth, sm->addr);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003651#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003652}
3653
3654
3655SM_STEP(WPA_PTK)
3656{
3657 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
Hai Shalomfdcde762020-04-02 11:19:20 -07003658 struct wpa_auth_config *conf = &wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003659
3660 if (sm->Init)
3661 SM_ENTER(WPA_PTK, INITIALIZE);
3662 else if (sm->Disconnect
3663 /* || FIX: dot11RSNAConfigSALifetime timeout */) {
3664 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
3665 "WPA_PTK: sm->Disconnect");
3666 SM_ENTER(WPA_PTK, DISCONNECT);
3667 }
3668 else if (sm->DeauthenticationRequest)
3669 SM_ENTER(WPA_PTK, DISCONNECTED);
3670 else if (sm->AuthenticationRequest)
3671 SM_ENTER(WPA_PTK, AUTHENTICATION);
3672 else if (sm->ReAuthenticationRequest)
3673 SM_ENTER(WPA_PTK, AUTHENTICATION2);
Jouni Malinen1420a892017-10-01 12:32:57 +03003674 else if (sm->PTKRequest) {
3675 if (wpa_auth_sm_ptk_update(sm) < 0)
3676 SM_ENTER(WPA_PTK, DISCONNECTED);
3677 else
3678 SM_ENTER(WPA_PTK, PTKSTART);
3679 } else switch (sm->wpa_ptk_state) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003680 case WPA_PTK_INITIALIZE:
3681 break;
3682 case WPA_PTK_DISCONNECT:
3683 SM_ENTER(WPA_PTK, DISCONNECTED);
3684 break;
3685 case WPA_PTK_DISCONNECTED:
3686 SM_ENTER(WPA_PTK, INITIALIZE);
3687 break;
3688 case WPA_PTK_AUTHENTICATION:
3689 SM_ENTER(WPA_PTK, AUTHENTICATION2);
3690 break;
3691 case WPA_PTK_AUTHENTICATION2:
3692 if (wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) &&
Hai Shalomfdcde762020-04-02 11:19:20 -07003693 wpa_auth_get_eapol(wpa_auth, sm->addr,
Hai Shalome21d4e82020-04-29 16:34:06 -07003694 WPA_EAPOL_keyRun))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003695 SM_ENTER(WPA_PTK, INITPMK);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003696 else if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
3697 sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003698 /* FIX: && 802.1X::keyRun */)
3699 SM_ENTER(WPA_PTK, INITPSK);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003700 else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP)
3701 SM_ENTER(WPA_PTK, INITPMK);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003702 break;
3703 case WPA_PTK_INITPMK:
Hai Shalomfdcde762020-04-02 11:19:20 -07003704 if (wpa_auth_get_eapol(wpa_auth, sm->addr,
Hai Shalome21d4e82020-04-29 16:34:06 -07003705 WPA_EAPOL_keyAvailable)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003706 SM_ENTER(WPA_PTK, PTKSTART);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003707#ifdef CONFIG_DPP
3708 } else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP && sm->pmksa) {
3709 SM_ENTER(WPA_PTK, PTKSTART);
3710#endif /* CONFIG_DPP */
3711 } else {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003712 wpa_auth->dot11RSNA4WayHandshakeFailures++;
Hai Shalomfdcde762020-04-02 11:19:20 -07003713 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003714 "INITPMK - keyAvailable = false");
3715 SM_ENTER(WPA_PTK, DISCONNECT);
3716 }
3717 break;
3718 case WPA_PTK_INITPSK:
Hai Shalomfdcde762020-04-02 11:19:20 -07003719 if (wpa_auth_get_psk(wpa_auth, sm->addr, sm->p2p_dev_addr,
Hai Shalom021b0b52019-04-10 11:17:58 -07003720 NULL, NULL, NULL)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003721 SM_ENTER(WPA_PTK, PTKSTART);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003722#ifdef CONFIG_SAE
3723 } else if (wpa_auth_uses_sae(sm) && sm->pmksa) {
3724 SM_ENTER(WPA_PTK, PTKSTART);
3725#endif /* CONFIG_SAE */
3726 } else {
Hai Shalomfdcde762020-04-02 11:19:20 -07003727 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003728 "no PSK configured for the STA");
3729 wpa_auth->dot11RSNA4WayHandshakeFailures++;
3730 SM_ENTER(WPA_PTK, DISCONNECT);
3731 }
3732 break;
3733 case WPA_PTK_PTKSTART:
3734 if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest &&
3735 sm->EAPOLKeyPairwise)
3736 SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING);
Hai Shalomfdcde762020-04-02 11:19:20 -07003737 else if (sm->TimeoutCtr > conf->wpa_pairwise_update_count) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003738 wpa_auth->dot11RSNA4WayHandshakeFailures++;
Hai Shalomfdcde762020-04-02 11:19:20 -07003739 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
3740 "PTKSTART: Retry limit %u reached",
3741 conf->wpa_pairwise_update_count);
Hai Shalome21d4e82020-04-29 16:34:06 -07003742 sm->disconnect_reason =
3743 WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003744 SM_ENTER(WPA_PTK, DISCONNECT);
3745 } else if (sm->TimeoutEvt)
3746 SM_ENTER(WPA_PTK, PTKSTART);
3747 break;
3748 case WPA_PTK_PTKCALCNEGOTIATING:
3749 if (sm->MICVerified)
3750 SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING2);
3751 else if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest &&
3752 sm->EAPOLKeyPairwise)
3753 SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING);
3754 else if (sm->TimeoutEvt)
3755 SM_ENTER(WPA_PTK, PTKSTART);
3756 break;
3757 case WPA_PTK_PTKCALCNEGOTIATING2:
3758 SM_ENTER(WPA_PTK, PTKINITNEGOTIATING);
3759 break;
3760 case WPA_PTK_PTKINITNEGOTIATING:
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003761 if (sm->update_snonce)
3762 SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING);
3763 else if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest &&
3764 sm->EAPOLKeyPairwise && sm->MICVerified)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003765 SM_ENTER(WPA_PTK, PTKINITDONE);
3766 else if (sm->TimeoutCtr >
Hai Shalomfdcde762020-04-02 11:19:20 -07003767 conf->wpa_pairwise_update_count ||
3768 (conf->wpa_disable_eapol_key_retries &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003769 sm->TimeoutCtr > 1)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003770 wpa_auth->dot11RSNA4WayHandshakeFailures++;
Hai Shalomfdcde762020-04-02 11:19:20 -07003771 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
3772 "PTKINITNEGOTIATING: Retry limit %u reached",
3773 conf->wpa_pairwise_update_count);
Hai Shalome21d4e82020-04-29 16:34:06 -07003774 sm->disconnect_reason =
3775 WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003776 SM_ENTER(WPA_PTK, DISCONNECT);
3777 } else if (sm->TimeoutEvt)
3778 SM_ENTER(WPA_PTK, PTKINITNEGOTIATING);
3779 break;
3780 case WPA_PTK_PTKINITDONE:
3781 break;
3782 }
3783}
3784
3785
3786SM_STATE(WPA_PTK_GROUP, IDLE)
3787{
3788 SM_ENTRY_MA(WPA_PTK_GROUP, IDLE, wpa_ptk_group);
3789 if (sm->Init) {
3790 /* Init flag is not cleared here, so avoid busy
3791 * loop by claiming nothing changed. */
Hai Shalome21d4e82020-04-29 16:34:06 -07003792 sm->changed = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003793 }
3794 sm->GTimeoutCtr = 0;
3795}
3796
3797
3798SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING)
3799{
3800 u8 rsc[WPA_KEY_RSC_LEN];
3801 struct wpa_group *gsm = sm->group;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003802 const u8 *kde;
3803 u8 *kde_buf = NULL, *pos, hdr[2];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003804 size_t kde_len;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003805 u8 *gtk, dummy_gtk[32];
Hai Shalomfdcde762020-04-02 11:19:20 -07003806 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003807
3808 SM_ENTRY_MA(WPA_PTK_GROUP, REKEYNEGOTIATING, wpa_ptk_group);
3809
3810 sm->GTimeoutCtr++;
Hai Shalomfdcde762020-04-02 11:19:20 -07003811 if (conf->wpa_disable_eapol_key_retries && sm->GTimeoutCtr > 1) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003812 /* Do not allow retransmission of EAPOL-Key group msg 1/2 */
3813 return;
3814 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003815 if (sm->GTimeoutCtr > conf->wpa_group_update_count) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003816 /* No point in sending the EAPOL-Key - we will disconnect
3817 * immediately following this. */
3818 return;
3819 }
3820
3821 if (sm->wpa == WPA_VERSION_WPA)
Hai Shalome21d4e82020-04-29 16:34:06 -07003822 sm->PInitAKeys = false;
3823 sm->TimeoutEvt = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003824 /* Send EAPOL(1, 1, 1, !Pair, G, RSC, GNonce, MIC(PTK), GTK[GN]) */
3825 os_memset(rsc, 0, WPA_KEY_RSC_LEN);
3826 if (gsm->wpa_group_state == WPA_GROUP_SETKEYSDONE)
3827 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc);
3828 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
3829 "sending 1/2 msg of Group Key Handshake");
3830
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003831 gtk = gsm->GTK[gsm->GN - 1];
Hai Shalomfdcde762020-04-02 11:19:20 -07003832 if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003833 /*
3834 * Provide unique random GTK to each STA to prevent use
3835 * of GTK in the BSS.
3836 */
3837 if (random_get_bytes(dummy_gtk, gsm->GTK_len) < 0)
3838 return;
3839 gtk = dummy_gtk;
3840 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003841 if (sm->wpa == WPA_VERSION_WPA2) {
3842 kde_len = 2 + RSN_SELECTOR_LEN + 2 + gsm->GTK_len +
Hai Shalom74f70d42019-02-11 14:42:39 -08003843 ieee80211w_kde_len(sm) + ocv_oci_len(sm);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003844 kde_buf = os_malloc(kde_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07003845 if (!kde_buf)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003846 return;
3847
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003848 kde = pos = kde_buf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003849 hdr[0] = gsm->GN & 0x03;
3850 hdr[1] = 0;
3851 pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003852 gtk, gsm->GTK_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003853 pos = ieee80211w_kde_add(sm, pos);
Hai Shalom899fcc72020-10-19 14:38:18 -07003854 if (ocv_oci_add(sm, &pos,
3855 conf->oci_freq_override_eapol_g1) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -08003856 os_free(kde_buf);
3857 return;
3858 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003859 kde_len = pos - kde;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003860 } else {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003861 kde = gtk;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003862 kde_len = gsm->GTK_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003863 }
3864
3865 wpa_send_eapol(sm->wpa_auth, sm,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003866 WPA_KEY_INFO_SECURE |
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003867 (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
3868 WPA_KEY_INFO_MIC : 0) |
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003869 WPA_KEY_INFO_ACK |
3870 (!sm->Pair ? WPA_KEY_INFO_INSTALL : 0),
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003871 rsc, NULL, kde, kde_len, gsm->GN, 1);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003872
3873 os_free(kde_buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003874}
3875
3876
3877SM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED)
3878{
Hai Shalom74f70d42019-02-11 14:42:39 -08003879 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
Hai Shalomfdcde762020-04-02 11:19:20 -07003880#ifdef CONFIG_OCV
Hai Shalom74f70d42019-02-11 14:42:39 -08003881 const u8 *key_data, *mic;
3882 struct ieee802_1x_hdr *hdr;
3883 struct wpa_eapol_key *key;
3884 struct wpa_eapol_ie_parse kde;
3885 size_t mic_len;
3886 u16 key_data_length;
3887#endif /* CONFIG_OCV */
3888
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003889 SM_ENTRY_MA(WPA_PTK_GROUP, REKEYESTABLISHED, wpa_ptk_group);
Hai Shalome21d4e82020-04-29 16:34:06 -07003890 sm->EAPOLKeyReceived = false;
Hai Shalom74f70d42019-02-11 14:42:39 -08003891
3892#ifdef CONFIG_OCV
3893 mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
3894
3895 /*
3896 * Note: last_rx_eapol_key length fields have already been validated in
3897 * wpa_receive().
3898 */
3899 hdr = (struct ieee802_1x_hdr *) sm->last_rx_eapol_key;
3900 key = (struct wpa_eapol_key *) (hdr + 1);
3901 mic = (u8 *) (key + 1);
3902 key_data = mic + mic_len + 2;
3903 key_data_length = WPA_GET_BE16(mic + mic_len);
3904 if (key_data_length > sm->last_rx_eapol_key_len - sizeof(*hdr) -
3905 sizeof(*key) - mic_len - 2)
3906 return;
3907
3908 if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) {
3909 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
3910 "received EAPOL-Key group msg 2/2 with invalid Key Data contents");
3911 return;
3912 }
3913
3914 if (wpa_auth_uses_ocv(sm)) {
3915 struct wpa_channel_info ci;
3916 int tx_chanwidth;
3917 int tx_seg1_idx;
3918
3919 if (wpa_channel_info(wpa_auth, &ci) != 0) {
3920 wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
Hai Shalom899fcc72020-10-19 14:38:18 -07003921 "Failed to get channel info to validate received OCI in EAPOL-Key group 2/2");
Hai Shalom74f70d42019-02-11 14:42:39 -08003922 return;
3923 }
3924
3925 if (get_sta_tx_parameters(sm,
3926 channel_width_to_int(ci.chanwidth),
3927 ci.seg1_idx, &tx_chanwidth,
3928 &tx_seg1_idx) < 0)
3929 return;
3930
3931 if (ocv_verify_tx_params(kde.oci, kde.oci_len, &ci,
Hai Shalom899fcc72020-10-19 14:38:18 -07003932 tx_chanwidth, tx_seg1_idx) !=
3933 OCI_SUCCESS) {
3934 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
3935 "OCV failed: %s", ocv_errorstr);
3936 if (wpa_auth->conf.msg_ctx)
3937 wpa_msg(wpa_auth->conf.msg_ctx, MSG_INFO,
3938 OCV_FAILURE "addr=" MACSTR
3939 " frame=eapol-key-g2 error=%s",
3940 MAC2STR(sm->addr), ocv_errorstr);
Hai Shalom74f70d42019-02-11 14:42:39 -08003941 return;
3942 }
3943 }
3944#endif /* CONFIG_OCV */
3945
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003946 if (sm->GUpdateStationKeys)
3947 sm->group->GKeyDoneStations--;
Hai Shalome21d4e82020-04-29 16:34:06 -07003948 sm->GUpdateStationKeys = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003949 sm->GTimeoutCtr = 0;
3950 /* FIX: MLME.SetProtection.Request(TA, Tx_Rx) */
Hai Shalomfdcde762020-04-02 11:19:20 -07003951 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003952 "group key handshake completed (%s)",
3953 sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN");
Hai Shalome21d4e82020-04-29 16:34:06 -07003954 sm->has_GTK = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003955}
3956
3957
3958SM_STATE(WPA_PTK_GROUP, KEYERROR)
3959{
3960 SM_ENTRY_MA(WPA_PTK_GROUP, KEYERROR, wpa_ptk_group);
3961 if (sm->GUpdateStationKeys)
3962 sm->group->GKeyDoneStations--;
Hai Shalome21d4e82020-04-29 16:34:06 -07003963 sm->GUpdateStationKeys = false;
3964 sm->Disconnect = true;
3965 sm->disconnect_reason = WLAN_REASON_GROUP_KEY_UPDATE_TIMEOUT;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003966 wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO,
3967 "group key handshake failed (%s) after %u tries",
3968 sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN",
3969 sm->wpa_auth->conf.wpa_group_update_count);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003970}
3971
3972
3973SM_STEP(WPA_PTK_GROUP)
3974{
3975 if (sm->Init || sm->PtkGroupInit) {
3976 SM_ENTER(WPA_PTK_GROUP, IDLE);
Hai Shalome21d4e82020-04-29 16:34:06 -07003977 sm->PtkGroupInit = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003978 } else switch (sm->wpa_ptk_group_state) {
3979 case WPA_PTK_GROUP_IDLE:
3980 if (sm->GUpdateStationKeys ||
3981 (sm->wpa == WPA_VERSION_WPA && sm->PInitAKeys))
3982 SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING);
3983 break;
3984 case WPA_PTK_GROUP_REKEYNEGOTIATING:
3985 if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest &&
3986 !sm->EAPOLKeyPairwise && sm->MICVerified)
3987 SM_ENTER(WPA_PTK_GROUP, REKEYESTABLISHED);
3988 else if (sm->GTimeoutCtr >
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003989 sm->wpa_auth->conf.wpa_group_update_count ||
3990 (sm->wpa_auth->conf.wpa_disable_eapol_key_retries &&
3991 sm->GTimeoutCtr > 1))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003992 SM_ENTER(WPA_PTK_GROUP, KEYERROR);
3993 else if (sm->TimeoutEvt)
3994 SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING);
3995 break;
3996 case WPA_PTK_GROUP_KEYERROR:
3997 SM_ENTER(WPA_PTK_GROUP, IDLE);
3998 break;
3999 case WPA_PTK_GROUP_REKEYESTABLISHED:
4000 SM_ENTER(WPA_PTK_GROUP, IDLE);
4001 break;
4002 }
4003}
4004
4005
4006static int wpa_gtk_update(struct wpa_authenticator *wpa_auth,
4007 struct wpa_group *group)
4008{
Hai Shalomfdcde762020-04-02 11:19:20 -07004009 struct wpa_auth_config *conf = &wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004010 int ret = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07004011 size_t len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004012
4013 os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
4014 inc_byte_array(group->Counter, WPA_NONCE_LEN);
4015 if (wpa_gmk_to_gtk(group->GMK, "Group key expansion",
4016 wpa_auth->addr, group->GNonce,
4017 group->GTK[group->GN - 1], group->GTK_len) < 0)
4018 ret = -1;
4019 wpa_hexdump_key(MSG_DEBUG, "GTK",
4020 group->GTK[group->GN - 1], group->GTK_len);
4021
Hai Shalomfdcde762020-04-02 11:19:20 -07004022 if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
4023 len = wpa_cipher_key_len(conf->group_mgmt_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004024 os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
4025 inc_byte_array(group->Counter, WPA_NONCE_LEN);
4026 if (wpa_gmk_to_gtk(group->GMK, "IGTK key expansion",
4027 wpa_auth->addr, group->GNonce,
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004028 group->IGTK[group->GN_igtk - 4], len) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004029 ret = -1;
4030 wpa_hexdump_key(MSG_DEBUG, "IGTK",
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004031 group->IGTK[group->GN_igtk - 4], len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004032 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004033
Hai Shalomfdcde762020-04-02 11:19:20 -07004034 if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION &&
4035 conf->beacon_prot) {
4036 len = wpa_cipher_key_len(conf->group_mgmt_cipher);
4037 os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
4038 inc_byte_array(group->Counter, WPA_NONCE_LEN);
4039 if (wpa_gmk_to_gtk(group->GMK, "BIGTK key expansion",
4040 wpa_auth->addr, group->GNonce,
4041 group->BIGTK[group->GN_bigtk - 6], len) < 0)
4042 ret = -1;
4043 wpa_hexdump_key(MSG_DEBUG, "BIGTK",
4044 group->BIGTK[group->GN_bigtk - 6], len);
4045 }
4046
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004047 return ret;
4048}
4049
4050
4051static void wpa_group_gtk_init(struct wpa_authenticator *wpa_auth,
4052 struct wpa_group *group)
4053{
Hai Shalomfdcde762020-04-02 11:19:20 -07004054 wpa_printf(MSG_DEBUG,
4055 "WPA: group state machine entering state GTK_INIT (VLAN-ID %d)",
4056 group->vlan_id);
Hai Shalome21d4e82020-04-29 16:34:06 -07004057 group->changed = false; /* GInit is not cleared here; avoid loop */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004058 group->wpa_group_state = WPA_GROUP_GTK_INIT;
4059
4060 /* GTK[0..N] = 0 */
4061 os_memset(group->GTK, 0, sizeof(group->GTK));
4062 group->GN = 1;
4063 group->GM = 2;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004064 group->GN_igtk = 4;
4065 group->GM_igtk = 5;
Hai Shalomfdcde762020-04-02 11:19:20 -07004066 group->GN_bigtk = 6;
4067 group->GM_bigtk = 7;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004068 /* GTK[GN] = CalcGTK() */
4069 wpa_gtk_update(wpa_auth, group);
4070}
4071
4072
4073static int wpa_group_update_sta(struct wpa_state_machine *sm, void *ctx)
4074{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004075 if (ctx != NULL && ctx != sm->group)
4076 return 0;
4077
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004078 if (sm->wpa_ptk_state != WPA_PTK_PTKINITDONE) {
4079 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
4080 "Not in PTKINITDONE; skip Group Key update");
Hai Shalome21d4e82020-04-29 16:34:06 -07004081 sm->GUpdateStationKeys = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004082 return 0;
4083 }
4084 if (sm->GUpdateStationKeys) {
4085 /*
4086 * This should not really happen, so add a debug log entry.
4087 * Since we clear the GKeyDoneStations before the loop, the
4088 * station needs to be counted here anyway.
4089 */
4090 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07004091 "GUpdateStationKeys was already set when marking station for GTK rekeying");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004092 }
4093
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004094 /* Do not rekey GTK/IGTK when STA is in WNM-Sleep Mode */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004095 if (sm->is_wnmsleep)
4096 return 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004097
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004098 sm->group->GKeyDoneStations++;
Hai Shalome21d4e82020-04-29 16:34:06 -07004099 sm->GUpdateStationKeys = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004100
4101 wpa_sm_step(sm);
4102 return 0;
4103}
4104
4105
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004106#ifdef CONFIG_WNM_AP
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004107/* update GTK when exiting WNM-Sleep Mode */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004108void wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm)
4109{
Hai Shalomfdcde762020-04-02 11:19:20 -07004110 if (!sm || sm->is_wnmsleep)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004111 return;
4112
4113 wpa_group_update_sta(sm, NULL);
4114}
4115
4116
4117void wpa_set_wnmsleep(struct wpa_state_machine *sm, int flag)
4118{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004119 if (sm)
4120 sm->is_wnmsleep = !!flag;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004121}
4122
4123
4124int wpa_wnmsleep_gtk_subelem(struct wpa_state_machine *sm, u8 *pos)
4125{
Hai Shalom899fcc72020-10-19 14:38:18 -07004126 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004127 struct wpa_group *gsm = sm->group;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004128 u8 *start = pos;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004129
4130 /*
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004131 * GTK subelement:
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004132 * Sub-elem ID[1] | Length[1] | Key Info[2] | Key Length[1] | RSC[8] |
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004133 * Key[5..32]
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004134 */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004135 *pos++ = WNM_SLEEP_SUBELEM_GTK;
4136 *pos++ = 11 + gsm->GTK_len;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004137 /* Key ID in B0-B1 of Key Info */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004138 WPA_PUT_LE16(pos, gsm->GN & 0x03);
4139 pos += 2;
4140 *pos++ = gsm->GTK_len;
4141 if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, pos) != 0)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004142 return 0;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004143 pos += 8;
4144 os_memcpy(pos, gsm->GTK[gsm->GN - 1], gsm->GTK_len);
Hai Shalom899fcc72020-10-19 14:38:18 -07004145 if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
4146 /*
4147 * Provide unique random GTK to each STA to prevent use
4148 * of GTK in the BSS.
4149 */
4150 if (random_get_bytes(pos, gsm->GTK_len) < 0)
4151 return 0;
4152 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004153 pos += gsm->GTK_len;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004154
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004155 wpa_printf(MSG_DEBUG, "WNM: GTK Key ID %u in WNM-Sleep Mode exit",
4156 gsm->GN);
4157 wpa_hexdump_key(MSG_DEBUG, "WNM: GTK in WNM-Sleep Mode exit",
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004158 gsm->GTK[gsm->GN - 1], gsm->GTK_len);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004159
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004160 return pos - start;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004161}
4162
4163
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004164int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos)
4165{
Hai Shalom899fcc72020-10-19 14:38:18 -07004166 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004167 struct wpa_group *gsm = sm->group;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004168 u8 *start = pos;
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004169 size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004170
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004171 /*
4172 * IGTK subelement:
4173 * Sub-elem ID[1] | Length[1] | KeyID[2] | PN[6] | Key[16]
4174 */
4175 *pos++ = WNM_SLEEP_SUBELEM_IGTK;
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004176 *pos++ = 2 + 6 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004177 WPA_PUT_LE16(pos, gsm->GN_igtk);
4178 pos += 2;
4179 if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, pos) != 0)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004180 return 0;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004181 pos += 6;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004182
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004183 os_memcpy(pos, gsm->IGTK[gsm->GN_igtk - 4], len);
Hai Shalom899fcc72020-10-19 14:38:18 -07004184 if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
4185 /*
4186 * Provide unique random IGTK to each STA to prevent use
4187 * of IGTK in the BSS.
4188 */
4189 if (random_get_bytes(pos, len) < 0)
4190 return 0;
4191 }
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004192 pos += len;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004193
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004194 wpa_printf(MSG_DEBUG, "WNM: IGTK Key ID %u in WNM-Sleep Mode exit",
4195 gsm->GN_igtk);
4196 wpa_hexdump_key(MSG_DEBUG, "WNM: IGTK in WNM-Sleep Mode exit",
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004197 gsm->IGTK[gsm->GN_igtk - 4], len);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004198
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004199 return pos - start;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004200}
Hai Shalomc3565922019-10-28 11:58:20 -07004201
Hai Shalomfdcde762020-04-02 11:19:20 -07004202
4203int wpa_wnmsleep_bigtk_subelem(struct wpa_state_machine *sm, u8 *pos)
4204{
4205 struct wpa_group *gsm = sm->group;
4206 u8 *start = pos;
4207 size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
4208
4209 /*
4210 * BIGTK subelement:
4211 * Sub-elem ID[1] | Length[1] | KeyID[2] | PN[6] | Key[16]
4212 */
4213 *pos++ = WNM_SLEEP_SUBELEM_BIGTK;
4214 *pos++ = 2 + 6 + len;
4215 WPA_PUT_LE16(pos, gsm->GN_bigtk);
4216 pos += 2;
4217 if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_bigtk, pos) != 0)
4218 return 0;
4219 pos += 6;
4220
4221 os_memcpy(pos, gsm->BIGTK[gsm->GN_bigtk - 6], len);
Hai Shalom899fcc72020-10-19 14:38:18 -07004222 if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
4223 /*
4224 * Provide unique random BIGTK to each STA to prevent use
4225 * of BIGTK in the BSS.
4226 */
4227 if (random_get_bytes(pos, len) < 0)
4228 return 0;
4229 }
Hai Shalomfdcde762020-04-02 11:19:20 -07004230 pos += len;
4231
4232 wpa_printf(MSG_DEBUG, "WNM: BIGTK Key ID %u in WNM-Sleep Mode exit",
4233 gsm->GN_bigtk);
4234 wpa_hexdump_key(MSG_DEBUG, "WNM: BIGTK in WNM-Sleep Mode exit",
4235 gsm->IGTK[gsm->GN_bigtk - 6], len);
4236
4237 return pos - start;
4238}
4239
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004240#endif /* CONFIG_WNM_AP */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004241
4242
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004243static void wpa_group_setkeys(struct wpa_authenticator *wpa_auth,
4244 struct wpa_group *group)
4245{
4246 int tmp;
4247
Hai Shalomfdcde762020-04-02 11:19:20 -07004248 wpa_printf(MSG_DEBUG,
4249 "WPA: group state machine entering state SETKEYS (VLAN-ID %d)",
4250 group->vlan_id);
Hai Shalome21d4e82020-04-29 16:34:06 -07004251 group->changed = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004252 group->wpa_group_state = WPA_GROUP_SETKEYS;
Hai Shalome21d4e82020-04-29 16:34:06 -07004253 group->GTKReKey = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004254 tmp = group->GM;
4255 group->GM = group->GN;
4256 group->GN = tmp;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004257 tmp = group->GM_igtk;
4258 group->GM_igtk = group->GN_igtk;
4259 group->GN_igtk = tmp;
Hai Shalomfdcde762020-04-02 11:19:20 -07004260 tmp = group->GM_bigtk;
4261 group->GM_bigtk = group->GN_bigtk;
4262 group->GN_bigtk = tmp;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004263 /* "GKeyDoneStations = GNoStations" is done in more robust way by
4264 * counting the STAs that are marked with GUpdateStationKeys instead of
4265 * including all STAs that could be in not-yet-completed state. */
4266 wpa_gtk_update(wpa_auth, group);
4267
4268 if (group->GKeyDoneStations) {
Hai Shalomfdcde762020-04-02 11:19:20 -07004269 wpa_printf(MSG_DEBUG,
4270 "wpa_group_setkeys: Unexpected GKeyDoneStations=%d when starting new GTK rekey",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004271 group->GKeyDoneStations);
4272 group->GKeyDoneStations = 0;
4273 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004274 wpa_auth_for_each_sta(wpa_auth, wpa_group_update_sta, group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004275 wpa_printf(MSG_DEBUG, "wpa_group_setkeys: GKeyDoneStations=%d",
4276 group->GKeyDoneStations);
4277}
4278
4279
4280static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth,
4281 struct wpa_group *group)
4282{
Hai Shalomfdcde762020-04-02 11:19:20 -07004283 struct wpa_auth_config *conf = &wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004284 int ret = 0;
4285
4286 if (wpa_auth_set_key(wpa_auth, group->vlan_id,
Hai Shalomfdcde762020-04-02 11:19:20 -07004287 wpa_cipher_to_alg(conf->wpa_group),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004288 broadcast_ether_addr, group->GN,
Hai Shalomfdcde762020-04-02 11:19:20 -07004289 group->GTK[group->GN - 1], group->GTK_len,
4290 KEY_FLAG_GROUP_TX_DEFAULT) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004291 ret = -1;
4292
Hai Shalomfdcde762020-04-02 11:19:20 -07004293 if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004294 enum wpa_alg alg;
4295 size_t len;
4296
Hai Shalomfdcde762020-04-02 11:19:20 -07004297 alg = wpa_cipher_to_alg(conf->group_mgmt_cipher);
4298 len = wpa_cipher_key_len(conf->group_mgmt_cipher);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004299
4300 if (ret == 0 &&
4301 wpa_auth_set_key(wpa_auth, group->vlan_id, alg,
4302 broadcast_ether_addr, group->GN_igtk,
Hai Shalomfdcde762020-04-02 11:19:20 -07004303 group->IGTK[group->GN_igtk - 4], len,
4304 KEY_FLAG_GROUP_TX_DEFAULT) < 0)
4305 ret = -1;
4306
4307 if (ret == 0 && conf->beacon_prot &&
4308 wpa_auth_set_key(wpa_auth, group->vlan_id, alg,
4309 broadcast_ether_addr, group->GN_bigtk,
4310 group->BIGTK[group->GN_bigtk - 6], len,
4311 KEY_FLAG_GROUP_TX_DEFAULT) < 0)
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004312 ret = -1;
4313 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004314
4315 return ret;
4316}
4317
4318
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004319static int wpa_group_disconnect_cb(struct wpa_state_machine *sm, void *ctx)
4320{
4321 if (sm->group == ctx) {
4322 wpa_printf(MSG_DEBUG, "WPA: Mark STA " MACSTR
Hai Shalomfdcde762020-04-02 11:19:20 -07004323 " for disconnection due to fatal failure",
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004324 MAC2STR(sm->addr));
Hai Shalome21d4e82020-04-29 16:34:06 -07004325 sm->Disconnect = true;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004326 }
4327
4328 return 0;
4329}
4330
4331
4332static void wpa_group_fatal_failure(struct wpa_authenticator *wpa_auth,
4333 struct wpa_group *group)
4334{
Hai Shalomfdcde762020-04-02 11:19:20 -07004335 wpa_printf(MSG_DEBUG,
4336 "WPA: group state machine entering state FATAL_FAILURE");
Hai Shalome21d4e82020-04-29 16:34:06 -07004337 group->changed = true;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004338 group->wpa_group_state = WPA_GROUP_FATAL_FAILURE;
4339 wpa_auth_for_each_sta(wpa_auth, wpa_group_disconnect_cb, group);
4340}
4341
4342
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004343static int wpa_group_setkeysdone(struct wpa_authenticator *wpa_auth,
4344 struct wpa_group *group)
4345{
Hai Shalomfdcde762020-04-02 11:19:20 -07004346 wpa_printf(MSG_DEBUG,
4347 "WPA: group state machine entering state SETKEYSDONE (VLAN-ID %d)",
4348 group->vlan_id);
Hai Shalome21d4e82020-04-29 16:34:06 -07004349 group->changed = true;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004350 group->wpa_group_state = WPA_GROUP_SETKEYSDONE;
4351
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004352 if (wpa_group_config_group_keys(wpa_auth, group) < 0) {
4353 wpa_group_fatal_failure(wpa_auth, group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004354 return -1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004355 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004356
4357 return 0;
4358}
4359
4360
4361static void wpa_group_sm_step(struct wpa_authenticator *wpa_auth,
4362 struct wpa_group *group)
4363{
4364 if (group->GInit) {
4365 wpa_group_gtk_init(wpa_auth, group);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004366 } else if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) {
4367 /* Do not allow group operations */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004368 } else if (group->wpa_group_state == WPA_GROUP_GTK_INIT &&
4369 group->GTKAuthenticator) {
4370 wpa_group_setkeysdone(wpa_auth, group);
4371 } else if (group->wpa_group_state == WPA_GROUP_SETKEYSDONE &&
4372 group->GTKReKey) {
4373 wpa_group_setkeys(wpa_auth, group);
4374 } else if (group->wpa_group_state == WPA_GROUP_SETKEYS) {
4375 if (group->GKeyDoneStations == 0)
4376 wpa_group_setkeysdone(wpa_auth, group);
4377 else if (group->GTKReKey)
4378 wpa_group_setkeys(wpa_auth, group);
4379 }
4380}
4381
4382
4383static int wpa_sm_step(struct wpa_state_machine *sm)
4384{
Hai Shalomfdcde762020-04-02 11:19:20 -07004385 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004386 return 0;
4387
4388 if (sm->in_step_loop) {
4389 /* This should not happen, but if it does, make sure we do not
4390 * end up freeing the state machine too early by exiting the
4391 * recursive call. */
4392 wpa_printf(MSG_ERROR, "WPA: wpa_sm_step() called recursively");
4393 return 0;
4394 }
4395
4396 sm->in_step_loop = 1;
4397 do {
4398 if (sm->pending_deinit)
4399 break;
4400
Hai Shalome21d4e82020-04-29 16:34:06 -07004401 sm->changed = false;
4402 sm->wpa_auth->group->changed = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004403
4404 SM_STEP_RUN(WPA_PTK);
4405 if (sm->pending_deinit)
4406 break;
4407 SM_STEP_RUN(WPA_PTK_GROUP);
4408 if (sm->pending_deinit)
4409 break;
4410 wpa_group_sm_step(sm->wpa_auth, sm->group);
4411 } while (sm->changed || sm->wpa_auth->group->changed);
4412 sm->in_step_loop = 0;
4413
4414 if (sm->pending_deinit) {
Hai Shalomfdcde762020-04-02 11:19:20 -07004415 wpa_printf(MSG_DEBUG,
4416 "WPA: Completing pending STA state machine deinit for "
4417 MACSTR, MAC2STR(sm->addr));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004418 wpa_free_sta_sm(sm);
4419 return 1;
4420 }
4421 return 0;
4422}
4423
4424
4425static void wpa_sm_call_step(void *eloop_ctx, void *timeout_ctx)
4426{
4427 struct wpa_state_machine *sm = eloop_ctx;
4428 wpa_sm_step(sm);
4429}
4430
4431
4432void wpa_auth_sm_notify(struct wpa_state_machine *sm)
4433{
Hai Shalomfdcde762020-04-02 11:19:20 -07004434 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004435 return;
4436 eloop_register_timeout(0, 0, wpa_sm_call_step, sm, NULL);
4437}
4438
4439
4440void wpa_gtk_rekey(struct wpa_authenticator *wpa_auth)
4441{
4442 int tmp, i;
4443 struct wpa_group *group;
4444
Hai Shalomfdcde762020-04-02 11:19:20 -07004445 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004446 return;
4447
4448 group = wpa_auth->group;
4449
4450 for (i = 0; i < 2; i++) {
4451 tmp = group->GM;
4452 group->GM = group->GN;
4453 group->GN = tmp;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004454 tmp = group->GM_igtk;
4455 group->GM_igtk = group->GN_igtk;
4456 group->GN_igtk = tmp;
Hai Shalomfdcde762020-04-02 11:19:20 -07004457 tmp = group->GM_bigtk;
4458 group->GM_bigtk = group->GN_bigtk;
4459 group->GN_bigtk = tmp;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004460 wpa_gtk_update(wpa_auth, group);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004461 wpa_group_config_group_keys(wpa_auth, group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004462 }
4463}
4464
4465
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004466static const char * wpa_bool_txt(int val)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004467{
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004468 return val ? "TRUE" : "FALSE";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004469}
4470
4471
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004472#define RSN_SUITE "%02x-%02x-%02x-%d"
4473#define RSN_SUITE_ARG(s) \
4474((s) >> 24) & 0xff, ((s) >> 16) & 0xff, ((s) >> 8) & 0xff, (s) & 0xff
4475
4476int wpa_get_mib(struct wpa_authenticator *wpa_auth, char *buf, size_t buflen)
4477{
Hai Shalomfdcde762020-04-02 11:19:20 -07004478 struct wpa_auth_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004479 int len = 0, ret;
4480 char pmkid_txt[PMKID_LEN * 2 + 1];
4481#ifdef CONFIG_RSN_PREAUTH
4482 const int preauth = 1;
4483#else /* CONFIG_RSN_PREAUTH */
4484 const int preauth = 0;
4485#endif /* CONFIG_RSN_PREAUTH */
4486
Hai Shalomfdcde762020-04-02 11:19:20 -07004487 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004488 return len;
Hai Shalomfdcde762020-04-02 11:19:20 -07004489 conf = &wpa_auth->conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004490
4491 ret = os_snprintf(buf + len, buflen - len,
4492 "dot11RSNAOptionImplemented=TRUE\n"
4493 "dot11RSNAPreauthenticationImplemented=%s\n"
4494 "dot11RSNAEnabled=%s\n"
4495 "dot11RSNAPreauthenticationEnabled=%s\n",
4496 wpa_bool_txt(preauth),
Hai Shalomfdcde762020-04-02 11:19:20 -07004497 wpa_bool_txt(conf->wpa & WPA_PROTO_RSN),
4498 wpa_bool_txt(conf->rsn_preauth));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004499 if (os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004500 return len;
4501 len += ret;
4502
4503 wpa_snprintf_hex(pmkid_txt, sizeof(pmkid_txt),
4504 wpa_auth->dot11RSNAPMKIDUsed, PMKID_LEN);
4505
4506 ret = os_snprintf(
4507 buf + len, buflen - len,
4508 "dot11RSNAConfigVersion=%u\n"
4509 "dot11RSNAConfigPairwiseKeysSupported=9999\n"
4510 /* FIX: dot11RSNAConfigGroupCipher */
4511 /* FIX: dot11RSNAConfigGroupRekeyMethod */
4512 /* FIX: dot11RSNAConfigGroupRekeyTime */
4513 /* FIX: dot11RSNAConfigGroupRekeyPackets */
4514 "dot11RSNAConfigGroupRekeyStrict=%u\n"
4515 "dot11RSNAConfigGroupUpdateCount=%u\n"
4516 "dot11RSNAConfigPairwiseUpdateCount=%u\n"
4517 "dot11RSNAConfigGroupCipherSize=%u\n"
4518 "dot11RSNAConfigPMKLifetime=%u\n"
4519 "dot11RSNAConfigPMKReauthThreshold=%u\n"
4520 "dot11RSNAConfigNumberOfPTKSAReplayCounters=0\n"
4521 "dot11RSNAConfigSATimeout=%u\n"
4522 "dot11RSNAAuthenticationSuiteSelected=" RSN_SUITE "\n"
4523 "dot11RSNAPairwiseCipherSelected=" RSN_SUITE "\n"
4524 "dot11RSNAGroupCipherSelected=" RSN_SUITE "\n"
4525 "dot11RSNAPMKIDUsed=%s\n"
4526 "dot11RSNAAuthenticationSuiteRequested=" RSN_SUITE "\n"
4527 "dot11RSNAPairwiseCipherRequested=" RSN_SUITE "\n"
4528 "dot11RSNAGroupCipherRequested=" RSN_SUITE "\n"
4529 "dot11RSNATKIPCounterMeasuresInvoked=%u\n"
4530 "dot11RSNA4WayHandshakeFailures=%u\n"
4531 "dot11RSNAConfigNumberOfGTKSAReplayCounters=0\n",
4532 RSN_VERSION,
Hai Shalomfdcde762020-04-02 11:19:20 -07004533 !!conf->wpa_strict_rekey,
4534 conf->wpa_group_update_count,
4535 conf->wpa_pairwise_update_count,
4536 wpa_cipher_key_len(conf->wpa_group) * 8,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004537 dot11RSNAConfigPMKLifetime,
4538 dot11RSNAConfigPMKReauthThreshold,
4539 dot11RSNAConfigSATimeout,
4540 RSN_SUITE_ARG(wpa_auth->dot11RSNAAuthenticationSuiteSelected),
4541 RSN_SUITE_ARG(wpa_auth->dot11RSNAPairwiseCipherSelected),
4542 RSN_SUITE_ARG(wpa_auth->dot11RSNAGroupCipherSelected),
4543 pmkid_txt,
4544 RSN_SUITE_ARG(wpa_auth->dot11RSNAAuthenticationSuiteRequested),
4545 RSN_SUITE_ARG(wpa_auth->dot11RSNAPairwiseCipherRequested),
4546 RSN_SUITE_ARG(wpa_auth->dot11RSNAGroupCipherRequested),
4547 wpa_auth->dot11RSNATKIPCounterMeasuresInvoked,
4548 wpa_auth->dot11RSNA4WayHandshakeFailures);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004549 if (os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004550 return len;
4551 len += ret;
4552
4553 /* TODO: dot11RSNAConfigPairwiseCiphersTable */
4554 /* TODO: dot11RSNAConfigAuthenticationSuitesTable */
4555
4556 /* Private MIB */
4557 ret = os_snprintf(buf + len, buflen - len, "hostapdWPAGroupState=%d\n",
4558 wpa_auth->group->wpa_group_state);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004559 if (os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004560 return len;
4561 len += ret;
4562
4563 return len;
4564}
4565
4566
4567int wpa_get_mib_sta(struct wpa_state_machine *sm, char *buf, size_t buflen)
4568{
4569 int len = 0, ret;
4570 u32 pairwise = 0;
4571
Hai Shalomfdcde762020-04-02 11:19:20 -07004572 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004573 return 0;
4574
4575 /* TODO: FF-FF-FF-FF-FF-FF entry for broadcast/multicast stats */
4576
4577 /* dot11RSNAStatsEntry */
4578
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07004579 pairwise = wpa_cipher_to_suite(sm->wpa == WPA_VERSION_WPA2 ?
4580 WPA_PROTO_RSN : WPA_PROTO_WPA,
4581 sm->pairwise);
4582 if (pairwise == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004583 return 0;
4584
4585 ret = os_snprintf(
4586 buf + len, buflen - len,
4587 /* TODO: dot11RSNAStatsIndex */
4588 "dot11RSNAStatsSTAAddress=" MACSTR "\n"
4589 "dot11RSNAStatsVersion=1\n"
4590 "dot11RSNAStatsSelectedPairwiseCipher=" RSN_SUITE "\n"
4591 /* TODO: dot11RSNAStatsTKIPICVErrors */
4592 "dot11RSNAStatsTKIPLocalMICFailures=%u\n"
4593 "dot11RSNAStatsTKIPRemoteMICFailures=%u\n"
4594 /* TODO: dot11RSNAStatsCCMPReplays */
4595 /* TODO: dot11RSNAStatsCCMPDecryptErrors */
4596 /* TODO: dot11RSNAStatsTKIPReplays */,
4597 MAC2STR(sm->addr),
4598 RSN_SUITE_ARG(pairwise),
4599 sm->dot11RSNAStatsTKIPLocalMICFailures,
4600 sm->dot11RSNAStatsTKIPRemoteMICFailures);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004601 if (os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004602 return len;
4603 len += ret;
4604
4605 /* Private MIB */
4606 ret = os_snprintf(buf + len, buflen - len,
Hai Shalomc3565922019-10-28 11:58:20 -07004607 "wpa=%d\n"
4608 "AKMSuiteSelector=" RSN_SUITE "\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004609 "hostapdWPAPTKState=%d\n"
4610 "hostapdWPAPTKGroupState=%d\n",
Hai Shalomc3565922019-10-28 11:58:20 -07004611 sm->wpa,
4612 RSN_SUITE_ARG(wpa_akm_to_suite(sm->wpa_key_mgmt)),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004613 sm->wpa_ptk_state,
4614 sm->wpa_ptk_group_state);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004615 if (os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004616 return len;
4617 len += ret;
4618
4619 return len;
4620}
4621
4622
4623void wpa_auth_countermeasures_start(struct wpa_authenticator *wpa_auth)
4624{
4625 if (wpa_auth)
4626 wpa_auth->dot11RSNATKIPCounterMeasuresInvoked++;
4627}
4628
4629
4630int wpa_auth_pairwise_set(struct wpa_state_machine *sm)
4631{
4632 return sm && sm->pairwise_set;
4633}
4634
4635
4636int wpa_auth_get_pairwise(struct wpa_state_machine *sm)
4637{
4638 return sm->pairwise;
4639}
4640
4641
Hai Shalom74f70d42019-02-11 14:42:39 -08004642const u8 * wpa_auth_get_pmk(struct wpa_state_machine *sm, int *len)
4643{
4644 if (!sm)
4645 return NULL;
4646 *len = sm->pmk_len;
4647 return sm->PMK;
4648}
4649
4650
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004651int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm)
4652{
Hai Shalomfdcde762020-04-02 11:19:20 -07004653 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004654 return -1;
4655 return sm->wpa_key_mgmt;
4656}
4657
4658
4659int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm)
4660{
Hai Shalomfdcde762020-04-02 11:19:20 -07004661 if (!sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004662 return 0;
4663 return sm->wpa;
4664}
4665
4666
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02004667int wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm)
4668{
4669 if (!sm || !wpa_key_mgmt_ft(sm->wpa_key_mgmt))
4670 return 0;
4671 return sm->tk_already_set;
4672}
4673
4674
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004675int wpa_auth_sta_fils_tk_already_set(struct wpa_state_machine *sm)
4676{
4677 if (!sm || !wpa_key_mgmt_fils(sm->wpa_key_mgmt))
4678 return 0;
4679 return sm->tk_already_set;
4680}
4681
4682
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004683int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm,
4684 struct rsn_pmksa_cache_entry *entry)
4685{
Hai Shalomfdcde762020-04-02 11:19:20 -07004686 if (!sm || sm->pmksa != entry)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004687 return -1;
4688 sm->pmksa = NULL;
4689 return 0;
4690}
4691
4692
4693struct rsn_pmksa_cache_entry *
4694wpa_auth_sta_get_pmksa(struct wpa_state_machine *sm)
4695{
4696 return sm ? sm->pmksa : NULL;
4697}
4698
4699
4700void wpa_auth_sta_local_mic_failure_report(struct wpa_state_machine *sm)
4701{
4702 if (sm)
4703 sm->dot11RSNAStatsTKIPLocalMICFailures++;
4704}
4705
4706
4707const u8 * wpa_auth_get_wpa_ie(struct wpa_authenticator *wpa_auth, size_t *len)
4708{
Hai Shalomfdcde762020-04-02 11:19:20 -07004709 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004710 return NULL;
4711 *len = wpa_auth->wpa_ie_len;
4712 return wpa_auth->wpa_ie;
4713}
4714
4715
4716int wpa_auth_pmksa_add(struct wpa_state_machine *sm, const u8 *pmk,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004717 unsigned int pmk_len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004718 int session_timeout, struct eapol_state_machine *eapol)
4719{
Hai Shalomfdcde762020-04-02 11:19:20 -07004720 if (!sm || sm->wpa != WPA_VERSION_WPA2 ||
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07004721 sm->wpa_auth->conf.disable_pmksa_caching)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004722 return -1;
4723
Hai Shalom81f62d82019-07-22 12:10:00 -07004724#ifdef CONFIG_IEEE80211R_AP
4725 if (pmk_len >= 2 * PMK_LEN && wpa_key_mgmt_ft(sm->wpa_key_mgmt) &&
4726 wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) &&
4727 !wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) {
4728 /* Cache MPMK/XXKey instead of initial part from MSK */
4729 pmk = pmk + PMK_LEN;
4730 pmk_len = PMK_LEN;
4731 } else
4732#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004733 if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004734 if (pmk_len > PMK_LEN_SUITE_B_192)
4735 pmk_len = PMK_LEN_SUITE_B_192;
4736 } else if (pmk_len > PMK_LEN) {
4737 pmk_len = PMK_LEN;
4738 }
4739
Hai Shalom81f62d82019-07-22 12:10:00 -07004740 wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK", pmk, pmk_len);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004741 if (pmksa_cache_auth_add(sm->wpa_auth->pmksa, pmk, pmk_len, NULL,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08004742 sm->PTK.kck, sm->PTK.kck_len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004743 sm->wpa_auth->addr, sm->addr, session_timeout,
4744 eapol, sm->wpa_key_mgmt))
4745 return 0;
4746
4747 return -1;
4748}
4749
4750
4751int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth,
4752 const u8 *pmk, size_t len, const u8 *sta_addr,
4753 int session_timeout,
4754 struct eapol_state_machine *eapol)
4755{
Hai Shalomfdcde762020-04-02 11:19:20 -07004756 if (!wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004757 return -1;
4758
Hai Shalom81f62d82019-07-22 12:10:00 -07004759 wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK from preauth", pmk, len);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004760 if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, len, NULL,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004761 NULL, 0,
4762 wpa_auth->addr,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004763 sta_addr, session_timeout, eapol,
4764 WPA_KEY_MGMT_IEEE8021X))
4765 return 0;
4766
4767 return -1;
4768}
4769
4770
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004771int wpa_auth_pmksa_add_sae(struct wpa_authenticator *wpa_auth, const u8 *addr,
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004772 const u8 *pmk, const u8 *pmkid)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004773{
4774 if (wpa_auth->conf.disable_pmksa_caching)
4775 return -1;
4776
Hai Shalom81f62d82019-07-22 12:10:00 -07004777 wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK from SAE", pmk, PMK_LEN);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004778 if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, PMK_LEN, pmkid,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004779 NULL, 0,
4780 wpa_auth->addr, addr, 0, NULL,
4781 WPA_KEY_MGMT_SAE))
4782 return 0;
4783
4784 return -1;
4785}
4786
4787
Roshan Pius3a1667e2018-07-03 15:17:14 -07004788void wpa_auth_add_sae_pmkid(struct wpa_state_machine *sm, const u8 *pmkid)
4789{
4790 os_memcpy(sm->pmkid, pmkid, PMKID_LEN);
4791 sm->pmkid_set = 1;
4792}
4793
4794
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004795int wpa_auth_pmksa_add2(struct wpa_authenticator *wpa_auth, const u8 *addr,
4796 const u8 *pmk, size_t pmk_len, const u8 *pmkid,
4797 int session_timeout, int akmp)
4798{
4799 if (wpa_auth->conf.disable_pmksa_caching)
4800 return -1;
4801
Hai Shalom81f62d82019-07-22 12:10:00 -07004802 wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK (2)", pmk, PMK_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004803 if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, pmk_len, pmkid,
4804 NULL, 0, wpa_auth->addr, addr, session_timeout,
4805 NULL, akmp))
4806 return 0;
4807
4808 return -1;
4809}
4810
4811
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004812void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth,
4813 const u8 *sta_addr)
4814{
4815 struct rsn_pmksa_cache_entry *pmksa;
4816
Hai Shalomfdcde762020-04-02 11:19:20 -07004817 if (!wpa_auth || !wpa_auth->pmksa)
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004818 return;
4819 pmksa = pmksa_cache_auth_get(wpa_auth->pmksa, sta_addr, NULL);
4820 if (pmksa) {
4821 wpa_printf(MSG_DEBUG, "WPA: Remove PMKSA cache entry for "
4822 MACSTR " based on request", MAC2STR(sta_addr));
4823 pmksa_cache_free_entry(wpa_auth->pmksa, pmksa);
4824 }
4825}
4826
4827
Dmitry Shmidte4663042016-04-04 10:07:49 -07004828int wpa_auth_pmksa_list(struct wpa_authenticator *wpa_auth, char *buf,
4829 size_t len)
4830{
4831 if (!wpa_auth || !wpa_auth->pmksa)
4832 return 0;
4833 return pmksa_cache_auth_list(wpa_auth->pmksa, buf, len);
4834}
4835
4836
4837void wpa_auth_pmksa_flush(struct wpa_authenticator *wpa_auth)
4838{
4839 if (wpa_auth && wpa_auth->pmksa)
4840 pmksa_cache_auth_flush(wpa_auth->pmksa);
4841}
4842
4843
Paul Stewart092955c2017-02-06 09:13:09 -08004844#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
4845#ifdef CONFIG_MESH
4846
4847int wpa_auth_pmksa_list_mesh(struct wpa_authenticator *wpa_auth, const u8 *addr,
4848 char *buf, size_t len)
4849{
4850 if (!wpa_auth || !wpa_auth->pmksa)
4851 return 0;
4852
4853 return pmksa_cache_auth_list_mesh(wpa_auth->pmksa, addr, buf, len);
4854}
4855
4856
4857struct rsn_pmksa_cache_entry *
4858wpa_auth_pmksa_create_entry(const u8 *aa, const u8 *spa, const u8 *pmk,
4859 const u8 *pmkid, int expiration)
4860{
4861 struct rsn_pmksa_cache_entry *entry;
4862 struct os_reltime now;
4863
4864 entry = pmksa_cache_auth_create_entry(pmk, PMK_LEN, pmkid, NULL, 0, aa,
4865 spa, 0, NULL, WPA_KEY_MGMT_SAE);
4866 if (!entry)
4867 return NULL;
4868
4869 os_get_reltime(&now);
4870 entry->expiration = now.sec + expiration;
4871 return entry;
4872}
4873
4874
4875int wpa_auth_pmksa_add_entry(struct wpa_authenticator *wpa_auth,
4876 struct rsn_pmksa_cache_entry *entry)
4877{
4878 int ret;
4879
4880 if (!wpa_auth || !wpa_auth->pmksa)
4881 return -1;
4882
4883 ret = pmksa_cache_auth_add_entry(wpa_auth->pmksa, entry);
4884 if (ret < 0)
4885 wpa_printf(MSG_DEBUG,
4886 "RSN: Failed to store external PMKSA cache for "
4887 MACSTR, MAC2STR(entry->spa));
4888
4889 return ret;
4890}
4891
4892#endif /* CONFIG_MESH */
4893#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
4894
4895
Dmitry Shmidte4663042016-04-04 10:07:49 -07004896struct rsn_pmksa_cache_entry *
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004897wpa_auth_pmksa_get(struct wpa_authenticator *wpa_auth, const u8 *sta_addr,
4898 const u8 *pmkid)
Dmitry Shmidte4663042016-04-04 10:07:49 -07004899{
4900 if (!wpa_auth || !wpa_auth->pmksa)
4901 return NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004902 return pmksa_cache_auth_get(wpa_auth->pmksa, sta_addr, pmkid);
Dmitry Shmidte4663042016-04-04 10:07:49 -07004903}
4904
4905
4906void wpa_auth_pmksa_set_to_sm(struct rsn_pmksa_cache_entry *pmksa,
4907 struct wpa_state_machine *sm,
4908 struct wpa_authenticator *wpa_auth,
4909 u8 *pmkid, u8 *pmk)
4910{
4911 if (!sm)
4912 return;
4913
4914 sm->pmksa = pmksa;
4915 os_memcpy(pmk, pmksa->pmk, PMK_LEN);
4916 os_memcpy(pmkid, pmksa->pmkid, PMKID_LEN);
4917 os_memcpy(wpa_auth->dot11RSNAPMKIDUsed, pmksa->pmkid, PMKID_LEN);
4918}
4919
4920
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004921/*
4922 * Remove and free the group from wpa_authenticator. This is triggered by a
4923 * callback to make sure nobody is currently iterating the group list while it
4924 * gets modified.
4925 */
4926static void wpa_group_free(struct wpa_authenticator *wpa_auth,
4927 struct wpa_group *group)
4928{
4929 struct wpa_group *prev = wpa_auth->group;
4930
4931 wpa_printf(MSG_DEBUG, "WPA: Remove group state machine for VLAN-ID %d",
4932 group->vlan_id);
4933
4934 while (prev) {
4935 if (prev->next == group) {
4936 /* This never frees the special first group as needed */
4937 prev->next = group->next;
4938 os_free(group);
4939 break;
4940 }
4941 prev = prev->next;
4942 }
4943
4944}
4945
4946
4947/* Increase the reference counter for group */
4948static void wpa_group_get(struct wpa_authenticator *wpa_auth,
4949 struct wpa_group *group)
4950{
4951 /* Skip the special first group */
4952 if (wpa_auth->group == group)
4953 return;
4954
4955 group->references++;
4956}
4957
4958
4959/* Decrease the reference counter and maybe free the group */
4960static void wpa_group_put(struct wpa_authenticator *wpa_auth,
4961 struct wpa_group *group)
4962{
4963 /* Skip the special first group */
4964 if (wpa_auth->group == group)
4965 return;
4966
4967 group->references--;
4968 if (group->references)
4969 return;
4970 wpa_group_free(wpa_auth, group);
4971}
4972
4973
4974/*
4975 * Add a group that has its references counter set to zero. Caller needs to
4976 * call wpa_group_get() on the return value to mark the entry in use.
4977 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004978static struct wpa_group *
4979wpa_auth_add_group(struct wpa_authenticator *wpa_auth, int vlan_id)
4980{
4981 struct wpa_group *group;
4982
Hai Shalomfdcde762020-04-02 11:19:20 -07004983 if (!wpa_auth || !wpa_auth->group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004984 return NULL;
4985
4986 wpa_printf(MSG_DEBUG, "WPA: Add group state machine for VLAN-ID %d",
4987 vlan_id);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004988 group = wpa_group_init(wpa_auth, vlan_id, 0);
Hai Shalomfdcde762020-04-02 11:19:20 -07004989 if (!group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004990 return NULL;
4991
4992 group->next = wpa_auth->group->next;
4993 wpa_auth->group->next = group;
4994
4995 return group;
4996}
4997
4998
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004999/*
5000 * Enforce that the group state machine for the VLAN is running, increase
5001 * reference counter as interface is up. References might have been increased
5002 * even if a negative value is returned.
5003 * Returns: -1 on error (group missing, group already failed); otherwise, 0
5004 */
5005int wpa_auth_ensure_group(struct wpa_authenticator *wpa_auth, int vlan_id)
5006{
5007 struct wpa_group *group;
5008
Hai Shalomfdcde762020-04-02 11:19:20 -07005009 if (!wpa_auth)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005010 return 0;
5011
5012 group = wpa_auth->group;
5013 while (group) {
5014 if (group->vlan_id == vlan_id)
5015 break;
5016 group = group->next;
5017 }
5018
Hai Shalomfdcde762020-04-02 11:19:20 -07005019 if (!group) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005020 group = wpa_auth_add_group(wpa_auth, vlan_id);
Hai Shalomfdcde762020-04-02 11:19:20 -07005021 if (!group)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005022 return -1;
5023 }
5024
5025 wpa_printf(MSG_DEBUG,
5026 "WPA: Ensure group state machine running for VLAN ID %d",
5027 vlan_id);
5028
5029 wpa_group_get(wpa_auth, group);
5030 group->num_setup_iface++;
5031
5032 if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
5033 return -1;
5034
5035 return 0;
5036}
5037
5038
5039/*
5040 * Decrease reference counter, expected to be zero afterwards.
5041 * returns: -1 on error (group not found, group in fail state)
5042 * -2 if wpa_group is still referenced
5043 * 0 else
5044 */
5045int wpa_auth_release_group(struct wpa_authenticator *wpa_auth, int vlan_id)
5046{
5047 struct wpa_group *group;
5048 int ret = 0;
5049
Hai Shalomfdcde762020-04-02 11:19:20 -07005050 if (!wpa_auth)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005051 return 0;
5052
5053 group = wpa_auth->group;
5054 while (group) {
5055 if (group->vlan_id == vlan_id)
5056 break;
5057 group = group->next;
5058 }
5059
Hai Shalomfdcde762020-04-02 11:19:20 -07005060 if (!group)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005061 return -1;
5062
5063 wpa_printf(MSG_DEBUG,
5064 "WPA: Try stopping group state machine for VLAN ID %d",
5065 vlan_id);
5066
5067 if (group->num_setup_iface <= 0) {
5068 wpa_printf(MSG_ERROR,
5069 "WPA: wpa_auth_release_group called more often than wpa_auth_ensure_group for VLAN ID %d, skipping.",
5070 vlan_id);
5071 return -1;
5072 }
5073 group->num_setup_iface--;
5074
5075 if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
5076 ret = -1;
5077
5078 if (group->references > 1) {
5079 wpa_printf(MSG_DEBUG,
5080 "WPA: Cannot stop group state machine for VLAN ID %d as references are still hold",
5081 vlan_id);
5082 ret = -2;
5083 }
5084
5085 wpa_group_put(wpa_auth, group);
5086
5087 return ret;
5088}
5089
5090
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005091int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id)
5092{
5093 struct wpa_group *group;
5094
Hai Shalomfdcde762020-04-02 11:19:20 -07005095 if (!sm || !sm->wpa_auth)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005096 return 0;
5097
5098 group = sm->wpa_auth->group;
5099 while (group) {
5100 if (group->vlan_id == vlan_id)
5101 break;
5102 group = group->next;
5103 }
5104
Hai Shalomfdcde762020-04-02 11:19:20 -07005105 if (!group) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005106 group = wpa_auth_add_group(sm->wpa_auth, vlan_id);
Hai Shalomfdcde762020-04-02 11:19:20 -07005107 if (!group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005108 return -1;
5109 }
5110
5111 if (sm->group == group)
5112 return 0;
5113
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005114 if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
5115 return -1;
5116
Hai Shalomfdcde762020-04-02 11:19:20 -07005117 wpa_printf(MSG_DEBUG, "WPA: Moving STA " MACSTR
5118 " to use group state machine for VLAN ID %d",
5119 MAC2STR(sm->addr), vlan_id);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005120
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005121 wpa_group_get(sm->wpa_auth, group);
5122 wpa_group_put(sm->wpa_auth, sm->group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005123 sm->group = group;
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07005124
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005125 return 0;
5126}
5127
5128
5129void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth,
5130 struct wpa_state_machine *sm, int ack)
5131{
Hai Shalomfdcde762020-04-02 11:19:20 -07005132 if (!wpa_auth || !sm)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005133 return;
5134 wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key TX status for STA " MACSTR
5135 " ack=%d", MAC2STR(sm->addr), ack);
5136 if (sm->pending_1_of_4_timeout && ack) {
5137 /*
5138 * Some deployed supplicant implementations update their SNonce
5139 * for each EAPOL-Key 2/4 message even within the same 4-way
5140 * handshake and then fail to use the first SNonce when
5141 * deriving the PTK. This results in unsuccessful 4-way
5142 * handshake whenever the relatively short initial timeout is
5143 * reached and EAPOL-Key 1/4 is retransmitted. Try to work
5144 * around this by increasing the timeout now that we know that
5145 * the station has received the frame.
5146 */
5147 int timeout_ms = eapol_key_timeout_subseq;
Hai Shalomfdcde762020-04-02 11:19:20 -07005148 wpa_printf(MSG_DEBUG,
5149 "WPA: Increase initial EAPOL-Key 1/4 timeout by %u ms because of acknowledged frame",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005150 timeout_ms);
5151 eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm);
5152 eloop_register_timeout(timeout_ms / 1000,
5153 (timeout_ms % 1000) * 1000,
5154 wpa_send_eapol_timeout, wpa_auth, sm);
5155 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005156
5157#ifdef CONFIG_TESTING_OPTIONS
5158 if (sm->eapol_status_cb) {
5159 sm->eapol_status_cb(sm->eapol_status_cb_ctx1,
5160 sm->eapol_status_cb_ctx2);
5161 sm->eapol_status_cb = NULL;
5162 }
5163#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005164}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005165
5166
5167int wpa_auth_uses_sae(struct wpa_state_machine *sm)
5168{
Hai Shalomfdcde762020-04-02 11:19:20 -07005169 if (!sm)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005170 return 0;
5171 return wpa_key_mgmt_sae(sm->wpa_key_mgmt);
5172}
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005173
5174
5175int wpa_auth_uses_ft_sae(struct wpa_state_machine *sm)
5176{
Hai Shalomfdcde762020-04-02 11:19:20 -07005177 if (!sm)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005178 return 0;
5179 return sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_SAE;
5180}
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08005181
5182
5183#ifdef CONFIG_P2P
5184int wpa_auth_get_ip_addr(struct wpa_state_machine *sm, u8 *addr)
5185{
Hai Shalomfdcde762020-04-02 11:19:20 -07005186 if (!sm || WPA_GET_BE32(sm->ip_addr) == 0)
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08005187 return -1;
5188 os_memcpy(addr, sm->ip_addr, 4);
5189 return 0;
5190}
5191#endif /* CONFIG_P2P */
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08005192
5193
5194int wpa_auth_radius_das_disconnect_pmksa(struct wpa_authenticator *wpa_auth,
5195 struct radius_das_attrs *attr)
5196{
5197 return pmksa_cache_auth_radius_das_disconnect(wpa_auth->pmksa, attr);
5198}
Dmitry Shmidt7f656022015-02-25 14:36:37 -08005199
5200
5201void wpa_auth_reconfig_group_keys(struct wpa_authenticator *wpa_auth)
5202{
5203 struct wpa_group *group;
5204
5205 if (!wpa_auth)
5206 return;
5207 for (group = wpa_auth->group; group; group = group->next)
5208 wpa_group_config_group_keys(wpa_auth, group);
5209}
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005210
5211
5212#ifdef CONFIG_FILS
5213
5214struct wpa_auth_fils_iter_data {
5215 struct wpa_authenticator *auth;
5216 const u8 *cache_id;
5217 struct rsn_pmksa_cache_entry *pmksa;
5218 const u8 *spa;
5219 const u8 *pmkid;
5220};
5221
5222
5223static int wpa_auth_fils_iter(struct wpa_authenticator *a, void *ctx)
5224{
5225 struct wpa_auth_fils_iter_data *data = ctx;
5226
5227 if (a == data->auth || !a->conf.fils_cache_id_set ||
5228 os_memcmp(a->conf.fils_cache_id, data->cache_id,
5229 FILS_CACHE_ID_LEN) != 0)
5230 return 0;
5231 data->pmksa = pmksa_cache_auth_get(a->pmksa, data->spa, data->pmkid);
5232 return data->pmksa != NULL;
5233}
5234
5235
5236struct rsn_pmksa_cache_entry *
5237wpa_auth_pmksa_get_fils_cache_id(struct wpa_authenticator *wpa_auth,
5238 const u8 *sta_addr, const u8 *pmkid)
5239{
5240 struct wpa_auth_fils_iter_data idata;
5241
5242 if (!wpa_auth->conf.fils_cache_id_set)
5243 return NULL;
5244 idata.auth = wpa_auth;
5245 idata.cache_id = wpa_auth->conf.fils_cache_id;
5246 idata.pmksa = NULL;
5247 idata.spa = sta_addr;
5248 idata.pmkid = pmkid;
5249 wpa_auth_for_each_auth(wpa_auth, wpa_auth_fils_iter, &idata);
5250 return idata.pmksa;
5251}
5252
5253
5254#ifdef CONFIG_IEEE80211R_AP
Roshan Pius3a1667e2018-07-03 15:17:14 -07005255int wpa_auth_write_fte(struct wpa_authenticator *wpa_auth, int use_sha384,
5256 u8 *buf, size_t len)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005257{
5258 struct wpa_auth_config *conf = &wpa_auth->conf;
5259
Roshan Pius3a1667e2018-07-03 15:17:14 -07005260 return wpa_write_ftie(conf, use_sha384, conf->r0_key_holder,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005261 conf->r0_key_holder_len,
Hai Shalomfdcde762020-04-02 11:19:20 -07005262 NULL, NULL, buf, len, NULL, 0, 0);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005263}
5264#endif /* CONFIG_IEEE80211R_AP */
5265
5266
5267void wpa_auth_get_fils_aead_params(struct wpa_state_machine *sm,
5268 u8 *fils_anonce, u8 *fils_snonce,
5269 u8 *fils_kek, size_t *fils_kek_len)
5270{
5271 os_memcpy(fils_anonce, sm->ANonce, WPA_NONCE_LEN);
5272 os_memcpy(fils_snonce, sm->SNonce, WPA_NONCE_LEN);
5273 os_memcpy(fils_kek, sm->PTK.kek, WPA_KEK_MAX_LEN);
5274 *fils_kek_len = sm->PTK.kek_len;
5275}
5276
Hai Shalom81f62d82019-07-22 12:10:00 -07005277
5278void wpa_auth_add_fils_pmk_pmkid(struct wpa_state_machine *sm, const u8 *pmk,
5279 size_t pmk_len, const u8 *pmkid)
5280{
5281 os_memcpy(sm->PMK, pmk, pmk_len);
5282 sm->pmk_len = pmk_len;
5283 os_memcpy(sm->pmkid, pmkid, PMKID_LEN);
5284 sm->pmkid_set = 1;
5285}
5286
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005287#endif /* CONFIG_FILS */
5288
5289
Hai Shalom021b0b52019-04-10 11:17:58 -07005290void wpa_auth_set_auth_alg(struct wpa_state_machine *sm, u16 auth_alg)
5291{
5292 if (sm)
5293 sm->auth_alg = auth_alg;
5294}
5295
5296
5297#ifdef CONFIG_DPP2
5298void wpa_auth_set_dpp_z(struct wpa_state_machine *sm, const struct wpabuf *z)
5299{
5300 if (sm) {
5301 wpabuf_clear_free(sm->dpp_z);
5302 sm->dpp_z = z ? wpabuf_dup(z) : NULL;
5303 }
5304}
5305#endif /* CONFIG_DPP2 */
5306
5307
Hai Shalom899fcc72020-10-19 14:38:18 -07005308void wpa_auth_set_transition_disable(struct wpa_authenticator *wpa_auth,
5309 u8 val)
5310{
5311 if (wpa_auth)
5312 wpa_auth->conf.transition_disable = val;
5313}
5314
5315
Roshan Pius3a1667e2018-07-03 15:17:14 -07005316#ifdef CONFIG_TESTING_OPTIONS
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005317
5318int wpa_auth_resend_m1(struct wpa_state_machine *sm, int change_anonce,
5319 void (*cb)(void *ctx1, void *ctx2),
5320 void *ctx1, void *ctx2)
5321{
5322 const u8 *anonce = sm->ANonce;
5323 u8 anonce_buf[WPA_NONCE_LEN];
5324
5325 if (change_anonce) {
5326 if (random_get_bytes(anonce_buf, WPA_NONCE_LEN))
5327 return -1;
5328 anonce = anonce_buf;
5329 }
5330
5331 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
5332 "sending 1/4 msg of 4-Way Handshake (TESTING)");
5333 wpa_send_eapol(sm->wpa_auth, sm,
5334 WPA_KEY_INFO_ACK | WPA_KEY_INFO_KEY_TYPE, NULL,
5335 anonce, NULL, 0, 0, 0);
5336 return 0;
5337}
5338
5339
5340int wpa_auth_resend_m3(struct wpa_state_machine *sm,
5341 void (*cb)(void *ctx1, void *ctx2),
5342 void *ctx1, void *ctx2)
5343{
Roshan Pius3a1667e2018-07-03 15:17:14 -07005344 u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde, *pos;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005345 u8 *opos;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005346 size_t gtk_len, kde_len;
Hai Shalom899fcc72020-10-19 14:38:18 -07005347 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005348 struct wpa_group *gsm = sm->group;
5349 u8 *wpa_ie;
Hai Shalomc3565922019-10-28 11:58:20 -07005350 int wpa_ie_len, secure, gtkidx, encr = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07005351 u8 hdr[2];
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005352
5353 /* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, [MDIE],
Hai Shalomfdcde762020-04-02 11:19:20 -07005354 GTK[GN], IGTK, [BIGTK], [FTIE], [TIE * 2])
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005355 */
5356
5357 /* Use 0 RSC */
5358 os_memset(rsc, 0, WPA_KEY_RSC_LEN);
5359 /* If FT is used, wpa_auth->wpa_ie includes both RSNIE and MDIE */
5360 wpa_ie = sm->wpa_auth->wpa_ie;
5361 wpa_ie_len = sm->wpa_auth->wpa_ie_len;
5362 if (sm->wpa == WPA_VERSION_WPA &&
5363 (sm->wpa_auth->conf.wpa & WPA_PROTO_RSN) &&
5364 wpa_ie_len > wpa_ie[1] + 2 && wpa_ie[0] == WLAN_EID_RSN) {
5365 /* WPA-only STA, remove RSN IE and possible MDIE */
5366 wpa_ie = wpa_ie + wpa_ie[1] + 2;
5367 if (wpa_ie[0] == WLAN_EID_MOBILITY_DOMAIN)
5368 wpa_ie = wpa_ie + wpa_ie[1] + 2;
5369 wpa_ie_len = wpa_ie[1] + 2;
5370 }
5371 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
5372 "sending 3/4 msg of 4-Way Handshake (TESTING)");
5373 if (sm->wpa == WPA_VERSION_WPA2) {
5374 /* WPA2 send GTK in the 4-way handshake */
5375 secure = 1;
5376 gtk = gsm->GTK[gsm->GN - 1];
5377 gtk_len = gsm->GTK_len;
Hai Shalomc3565922019-10-28 11:58:20 -07005378 gtkidx = gsm->GN;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005379 _rsc = rsc;
5380 encr = 1;
5381 } else {
5382 /* WPA does not include GTK in msg 3/4 */
5383 secure = 0;
5384 gtk = NULL;
5385 gtk_len = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005386 _rsc = NULL;
5387 if (sm->rx_eapol_key_secure) {
5388 /*
5389 * It looks like Windows 7 supplicant tries to use
5390 * Secure bit in msg 2/4 after having reported Michael
5391 * MIC failure and it then rejects the 4-way handshake
5392 * if msg 3/4 does not set Secure bit. Work around this
5393 * by setting the Secure bit here even in the case of
5394 * WPA if the supplicant used it first.
5395 */
5396 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
Hai Shalomfdcde762020-04-02 11:19:20 -07005397 "STA used Secure bit in WPA msg 2/4 - set Secure for 3/4 as workaround");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005398 secure = 1;
5399 }
5400 }
5401
Hai Shalom74f70d42019-02-11 14:42:39 -08005402 kde_len = wpa_ie_len + ieee80211w_kde_len(sm) + ocv_oci_len(sm);
Hai Shalomfdcde762020-04-02 11:19:20 -07005403
5404 if (sm->use_ext_key_id)
5405 kde_len += 2 + RSN_SELECTOR_LEN + 2;
5406
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005407 if (gtk)
5408 kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len;
5409#ifdef CONFIG_IEEE80211R_AP
5410 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
5411 kde_len += 2 + PMKID_LEN; /* PMKR1Name into RSN IE */
5412 kde_len += 300; /* FTIE + 2 * TIE */
5413 }
5414#endif /* CONFIG_IEEE80211R_AP */
5415 kde = os_malloc(kde_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07005416 if (!kde)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005417 return -1;
5418
5419 pos = kde;
5420 os_memcpy(pos, wpa_ie, wpa_ie_len);
5421 pos += wpa_ie_len;
5422#ifdef CONFIG_IEEE80211R_AP
5423 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
5424 int res;
5425 size_t elen;
5426
5427 elen = pos - kde;
5428 res = wpa_insert_pmkid(kde, &elen, sm->pmk_r1_name);
5429 if (res < 0) {
Hai Shalomfdcde762020-04-02 11:19:20 -07005430 wpa_printf(MSG_ERROR,
5431 "FT: Failed to insert PMKR1Name into RSN IE in EAPOL-Key data");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005432 os_free(kde);
5433 return -1;
5434 }
5435 pos -= wpa_ie_len;
5436 pos += elen;
5437 }
5438#endif /* CONFIG_IEEE80211R_AP */
Hai Shalomfdcde762020-04-02 11:19:20 -07005439 hdr[1] = 0;
5440
5441 if (sm->use_ext_key_id) {
5442 hdr[0] = sm->keyidx_active & 0x01;
5443 pos = wpa_add_kde(pos, RSN_KEY_DATA_KEYID, hdr, 2, NULL, 0);
5444 }
5445
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005446 if (gtk) {
Hai Shalomc3565922019-10-28 11:58:20 -07005447 hdr[0] = gtkidx & 0x03;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005448 pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
5449 gtk, gtk_len);
5450 }
5451 opos = pos;
5452 pos = ieee80211w_kde_add(sm, pos);
Roshan Pius3a1667e2018-07-03 15:17:14 -07005453 if (pos - opos >= 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN) {
5454 /* skip KDE header and keyid */
5455 opos += 2 + RSN_SELECTOR_LEN + 2;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005456 os_memset(opos, 0, 6); /* clear PN */
5457 }
Hai Shalom899fcc72020-10-19 14:38:18 -07005458 if (ocv_oci_add(sm, &pos, conf->oci_freq_override_eapol_m3) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -08005459 os_free(kde);
5460 return -1;
5461 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005462
5463#ifdef CONFIG_IEEE80211R_AP
5464 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
5465 int res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005466
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005467 if (sm->assoc_resp_ftie &&
5468 kde + kde_len - pos >= 2 + sm->assoc_resp_ftie[1]) {
5469 os_memcpy(pos, sm->assoc_resp_ftie,
5470 2 + sm->assoc_resp_ftie[1]);
5471 res = 2 + sm->assoc_resp_ftie[1];
5472 } else {
Roshan Pius3a1667e2018-07-03 15:17:14 -07005473 int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt);
5474
5475 res = wpa_write_ftie(conf, use_sha384,
5476 conf->r0_key_holder,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005477 conf->r0_key_holder_len,
5478 NULL, NULL, pos,
5479 kde + kde_len - pos,
Hai Shalomfdcde762020-04-02 11:19:20 -07005480 NULL, 0, 0);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005481 }
5482 if (res < 0) {
Hai Shalomfdcde762020-04-02 11:19:20 -07005483 wpa_printf(MSG_ERROR,
5484 "FT: Failed to insert FTIE into EAPOL-Key Key Data");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005485 os_free(kde);
5486 return -1;
5487 }
5488 pos += res;
5489
5490 /* TIE[ReassociationDeadline] (TU) */
5491 *pos++ = WLAN_EID_TIMEOUT_INTERVAL;
5492 *pos++ = 5;
5493 *pos++ = WLAN_TIMEOUT_REASSOC_DEADLINE;
5494 WPA_PUT_LE32(pos, conf->reassociation_deadline);
5495 pos += 4;
5496
5497 /* TIE[KeyLifetime] (seconds) */
5498 *pos++ = WLAN_EID_TIMEOUT_INTERVAL;
5499 *pos++ = 5;
5500 *pos++ = WLAN_TIMEOUT_KEY_LIFETIME;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005501 WPA_PUT_LE32(pos, conf->r0_key_lifetime);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005502 pos += 4;
5503 }
5504#endif /* CONFIG_IEEE80211R_AP */
5505
5506 wpa_send_eapol(sm->wpa_auth, sm,
5507 (secure ? WPA_KEY_INFO_SECURE : 0) |
5508 (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
5509 WPA_KEY_INFO_MIC : 0) |
5510 WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL |
5511 WPA_KEY_INFO_KEY_TYPE,
Hai Shalomc3565922019-10-28 11:58:20 -07005512 _rsc, sm->ANonce, kde, pos - kde, 0, encr);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005513 os_free(kde);
5514 return 0;
5515}
5516
5517
5518int wpa_auth_resend_group_m1(struct wpa_state_machine *sm,
5519 void (*cb)(void *ctx1, void *ctx2),
5520 void *ctx1, void *ctx2)
5521{
5522 u8 rsc[WPA_KEY_RSC_LEN];
Hai Shalom899fcc72020-10-19 14:38:18 -07005523 struct wpa_auth_config *conf = &sm->wpa_auth->conf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005524 struct wpa_group *gsm = sm->group;
5525 const u8 *kde;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005526 u8 *kde_buf = NULL, *pos, hdr[2];
Roshan Pius3a1667e2018-07-03 15:17:14 -07005527 u8 *opos;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005528 size_t kde_len;
5529 u8 *gtk;
5530
5531 /* Send EAPOL(1, 1, 1, !Pair, G, RSC, GNonce, MIC(PTK), GTK[GN]) */
5532 os_memset(rsc, 0, WPA_KEY_RSC_LEN);
5533 /* Use 0 RSC */
5534 wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
5535 "sending 1/2 msg of Group Key Handshake (TESTING)");
5536
5537 gtk = gsm->GTK[gsm->GN - 1];
5538 if (sm->wpa == WPA_VERSION_WPA2) {
5539 kde_len = 2 + RSN_SELECTOR_LEN + 2 + gsm->GTK_len +
Hai Shalom74f70d42019-02-11 14:42:39 -08005540 ieee80211w_kde_len(sm) + ocv_oci_len(sm);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005541 kde_buf = os_malloc(kde_len);
Hai Shalomfdcde762020-04-02 11:19:20 -07005542 if (!kde_buf)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005543 return -1;
5544
5545 kde = pos = kde_buf;
5546 hdr[0] = gsm->GN & 0x03;
5547 hdr[1] = 0;
5548 pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
5549 gtk, gsm->GTK_len);
5550 opos = pos;
5551 pos = ieee80211w_kde_add(sm, pos);
Roshan Pius3a1667e2018-07-03 15:17:14 -07005552 if (pos - opos >=
5553 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN) {
5554 /* skip KDE header and keyid */
5555 opos += 2 + RSN_SELECTOR_LEN + 2;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005556 os_memset(opos, 0, 6); /* clear PN */
5557 }
Hai Shalom899fcc72020-10-19 14:38:18 -07005558 if (ocv_oci_add(sm, &pos,
5559 conf->oci_freq_override_eapol_g1) < 0) {
Hai Shalom74f70d42019-02-11 14:42:39 -08005560 os_free(kde_buf);
5561 return -1;
5562 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005563 kde_len = pos - kde;
5564 } else {
5565 kde = gtk;
5566 kde_len = gsm->GTK_len;
5567 }
5568
5569 sm->eapol_status_cb = cb;
5570 sm->eapol_status_cb_ctx1 = ctx1;
5571 sm->eapol_status_cb_ctx2 = ctx2;
5572
5573 wpa_send_eapol(sm->wpa_auth, sm,
5574 WPA_KEY_INFO_SECURE |
5575 (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
5576 WPA_KEY_INFO_MIC : 0) |
5577 WPA_KEY_INFO_ACK |
5578 (!sm->Pair ? WPA_KEY_INFO_INSTALL : 0),
5579 rsc, NULL, kde, kde_len, gsm->GN, 1);
5580
5581 os_free(kde_buf);
5582 return 0;
5583}
5584
Roshan Pius3a1667e2018-07-03 15:17:14 -07005585
5586int wpa_auth_rekey_gtk(struct wpa_authenticator *wpa_auth)
5587{
5588 if (!wpa_auth)
5589 return -1;
5590 eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL);
5591 return eloop_register_timeout(0, 0, wpa_rekey_gtk, wpa_auth, NULL);
5592}
5593
Hai Shalomb755a2a2020-04-23 21:49:02 -07005594
5595void wpa_auth_set_ft_rsnxe_used(struct wpa_authenticator *wpa_auth, int val)
5596{
5597 if (wpa_auth)
5598 wpa_auth->conf.ft_rsnxe_used = val;
5599}
5600
Hai Shalom899fcc72020-10-19 14:38:18 -07005601
5602void wpa_auth_set_ocv_override_freq(struct wpa_authenticator *wpa_auth,
5603 enum wpa_auth_ocv_override_frame frame,
5604 unsigned int freq)
5605{
5606 if (!wpa_auth)
5607 return;
5608 switch (frame) {
5609 case WPA_AUTH_OCV_OVERRIDE_EAPOL_M3:
5610 wpa_auth->conf.oci_freq_override_eapol_m3 = freq;
5611 break;
5612 case WPA_AUTH_OCV_OVERRIDE_EAPOL_G1:
5613 wpa_auth->conf.oci_freq_override_eapol_g1 = freq;
5614 break;
5615 case WPA_AUTH_OCV_OVERRIDE_FT_ASSOC:
5616 wpa_auth->conf.oci_freq_override_ft_assoc = freq;
5617 break;
5618 case WPA_AUTH_OCV_OVERRIDE_FILS_ASSOC:
5619 wpa_auth->conf.oci_freq_override_fils_assoc = freq;
5620 break;
5621 }
5622}
5623
Kai Shie75b0652020-11-24 20:31:29 -08005624void wpa_auth_set_skip_send_eapol(struct wpa_authenticator *wpa_auth,
5625 u8 val)
5626{
5627 if (wpa_auth)
5628 wpa_auth->conf.skip_send_eapol = val;
5629}
5630
5631void wpa_auth_set_enable_eapol_large_timeout(struct wpa_authenticator *wpa_auth,
5632 u8 val)
5633{
5634 if (wpa_auth)
5635 wpa_auth->conf.enable_eapol_large_timeout = val;
5636}
5637
5638
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005639#endif /* CONFIG_TESTING_OPTIONS */