1214501Srpaulo/*
2252726Srpaulo * IEEE 802.11 RSN / WPA Authenticator
3346981Scy * Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi>
4214501Srpaulo *
5252726Srpaulo * This software may be distributed under the terms of the BSD license.
6252726Srpaulo * See README for more details.
7214501Srpaulo */
8214501Srpaulo
9214501Srpaulo#include "utils/includes.h"
10214501Srpaulo
11214501Srpaulo#include "utils/common.h"
12214501Srpaulo#include "utils/eloop.h"
13214501Srpaulo#include "utils/state_machine.h"
14281806Srpaulo#include "utils/bitfield.h"
15214501Srpaulo#include "common/ieee802_11_defs.h"
16346981Scy#include "common/ocv.h"
17346981Scy#include "crypto/aes.h"
18214501Srpaulo#include "crypto/aes_wrap.h"
19346981Scy#include "crypto/aes_siv.h"
20214501Srpaulo#include "crypto/crypto.h"
21214501Srpaulo#include "crypto/sha1.h"
22214501Srpaulo#include "crypto/sha256.h"
23346981Scy#include "crypto/sha384.h"
24252726Srpaulo#include "crypto/random.h"
25214501Srpaulo#include "eapol_auth/eapol_auth_sm.h"
26346981Scy#include "drivers/driver.h"
27214501Srpaulo#include "ap_config.h"
28214501Srpaulo#include "ieee802_11.h"
29214501Srpaulo#include "wpa_auth.h"
30214501Srpaulo#include "pmksa_cache_auth.h"
31214501Srpaulo#include "wpa_auth_i.h"
32214501Srpaulo#include "wpa_auth_ie.h"
33214501Srpaulo
34214501Srpaulo#define STATE_MACHINE_DATA struct wpa_state_machine
35214501Srpaulo#define STATE_MACHINE_DEBUG_PREFIX "WPA"
36214501Srpaulo#define STATE_MACHINE_ADDR sm->addr
37214501Srpaulo
38214501Srpaulo
39214501Srpaulostatic void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx);
40214501Srpaulostatic int wpa_sm_step(struct wpa_state_machine *sm);
41346981Scystatic int wpa_verify_key_mic(int akmp, size_t pmk_len, struct wpa_ptk *PTK,
42346981Scy			      u8 *data, size_t data_len);
43346981Scy#ifdef CONFIG_FILS
44346981Scystatic int wpa_aead_decrypt(struct wpa_state_machine *sm, struct wpa_ptk *ptk,
45346981Scy			    u8 *buf, size_t buf_len, u16 *_key_data_len);
46346981Scystatic struct wpabuf * fils_prepare_plainbuf(struct wpa_state_machine *sm,
47346981Scy					     const struct wpabuf *hlp);
48346981Scy#endif /* CONFIG_FILS */
49214501Srpaulostatic void wpa_sm_call_step(void *eloop_ctx, void *timeout_ctx);
50214501Srpaulostatic void wpa_group_sm_step(struct wpa_authenticator *wpa_auth,
51214501Srpaulo			      struct wpa_group *group);
52214501Srpaulostatic void wpa_request_new_ptk(struct wpa_state_machine *sm);
53214501Srpaulostatic int wpa_gtk_update(struct wpa_authenticator *wpa_auth,
54214501Srpaulo			  struct wpa_group *group);
55252726Srpaulostatic int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth,
56252726Srpaulo				       struct wpa_group *group);
57281806Srpaulostatic int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
58337817Scy			  const u8 *pmk, unsigned int pmk_len,
59337817Scy			  struct wpa_ptk *ptk);
60289549Srpaulostatic void wpa_group_free(struct wpa_authenticator *wpa_auth,
61289549Srpaulo			   struct wpa_group *group);
62289549Srpaulostatic void wpa_group_get(struct wpa_authenticator *wpa_auth,
63289549Srpaulo			  struct wpa_group *group);
64289549Srpaulostatic void wpa_group_put(struct wpa_authenticator *wpa_auth,
65289549Srpaulo			  struct wpa_group *group);
66346981Scystatic u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos);
67214501Srpaulo
68214501Srpaulostatic const u32 eapol_key_timeout_first = 100; /* ms */
69214501Srpaulostatic const u32 eapol_key_timeout_subseq = 1000; /* ms */
70252726Srpaulostatic const u32 eapol_key_timeout_first_group = 500; /* ms */
71346981Scystatic const u32 eapol_key_timeout_no_retrans = 4000; /* ms */
72214501Srpaulo
73214501Srpaulo/* TODO: make these configurable */
74214501Srpaulostatic const int dot11RSNAConfigPMKLifetime = 43200;
75214501Srpaulostatic const int dot11RSNAConfigPMKReauthThreshold = 70;
76214501Srpaulostatic const int dot11RSNAConfigSATimeout = 60;
77214501Srpaulo
78214501Srpaulo
79252726Srpaulostatic inline int wpa_auth_mic_failure_report(
80214501Srpaulo	struct wpa_authenticator *wpa_auth, const u8 *addr)
81214501Srpaulo{
82346981Scy	if (wpa_auth->cb->mic_failure_report)
83346981Scy		return wpa_auth->cb->mic_failure_report(wpa_auth->cb_ctx, addr);
84252726Srpaulo	return 0;
85214501Srpaulo}
86214501Srpaulo
87214501Srpaulo
88289549Srpaulostatic inline void wpa_auth_psk_failure_report(
89289549Srpaulo	struct wpa_authenticator *wpa_auth, const u8 *addr)
90289549Srpaulo{
91346981Scy	if (wpa_auth->cb->psk_failure_report)
92346981Scy		wpa_auth->cb->psk_failure_report(wpa_auth->cb_ctx, addr);
93289549Srpaulo}
94289549Srpaulo
95289549Srpaulo
96214501Srpaulostatic inline void wpa_auth_set_eapol(struct wpa_authenticator *wpa_auth,
97214501Srpaulo				      const u8 *addr, wpa_eapol_variable var,
98214501Srpaulo				      int value)
99214501Srpaulo{
100346981Scy	if (wpa_auth->cb->set_eapol)
101346981Scy		wpa_auth->cb->set_eapol(wpa_auth->cb_ctx, addr, var, value);
102214501Srpaulo}
103214501Srpaulo
104214501Srpaulo
105214501Srpaulostatic inline int wpa_auth_get_eapol(struct wpa_authenticator *wpa_auth,
106214501Srpaulo				     const u8 *addr, wpa_eapol_variable var)
107214501Srpaulo{
108346981Scy	if (wpa_auth->cb->get_eapol == NULL)
109214501Srpaulo		return -1;
110346981Scy	return wpa_auth->cb->get_eapol(wpa_auth->cb_ctx, addr, var);
111214501Srpaulo}
112214501Srpaulo
113214501Srpaulo
114214501Srpaulostatic inline const u8 * wpa_auth_get_psk(struct wpa_authenticator *wpa_auth,
115281806Srpaulo					  const u8 *addr,
116281806Srpaulo					  const u8 *p2p_dev_addr,
117346981Scy					  const u8 *prev_psk, size_t *psk_len,
118346981Scy					  int *vlan_id)
119214501Srpaulo{
120346981Scy	if (wpa_auth->cb->get_psk == NULL)
121214501Srpaulo		return NULL;
122346981Scy	return wpa_auth->cb->get_psk(wpa_auth->cb_ctx, addr, p2p_dev_addr,
123346981Scy				     prev_psk, psk_len, vlan_id);
124214501Srpaulo}
125214501Srpaulo
126214501Srpaulo
127214501Srpaulostatic inline int wpa_auth_get_msk(struct wpa_authenticator *wpa_auth,
128214501Srpaulo				   const u8 *addr, u8 *msk, size_t *len)
129214501Srpaulo{
130346981Scy	if (wpa_auth->cb->get_msk == NULL)
131214501Srpaulo		return -1;
132346981Scy	return wpa_auth->cb->get_msk(wpa_auth->cb_ctx, addr, msk, len);
133214501Srpaulo}
134214501Srpaulo
135214501Srpaulo
136214501Srpaulostatic inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth,
137214501Srpaulo				   int vlan_id,
138214501Srpaulo				   enum wpa_alg alg, const u8 *addr, int idx,
139214501Srpaulo				   u8 *key, size_t key_len)
140214501Srpaulo{
141346981Scy	if (wpa_auth->cb->set_key == NULL)
142214501Srpaulo		return -1;
143346981Scy	return wpa_auth->cb->set_key(wpa_auth->cb_ctx, vlan_id, alg, addr, idx,
144346981Scy				     key, key_len);
145214501Srpaulo}
146214501Srpaulo
147214501Srpaulo
148214501Srpaulostatic inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth,
149214501Srpaulo				      const u8 *addr, int idx, u8 *seq)
150214501Srpaulo{
151346981Scy	if (wpa_auth->cb->get_seqnum == NULL)
152214501Srpaulo		return -1;
153346981Scy	return wpa_auth->cb->get_seqnum(wpa_auth->cb_ctx, addr, idx, seq);
154214501Srpaulo}
155214501Srpaulo
156214501Srpaulo
157214501Srpaulostatic inline int
158214501Srpaulowpa_auth_send_eapol(struct wpa_authenticator *wpa_auth, const u8 *addr,
159214501Srpaulo		    const u8 *data, size_t data_len, int encrypt)
160214501Srpaulo{
161346981Scy	if (wpa_auth->cb->send_eapol == NULL)
162214501Srpaulo		return -1;
163346981Scy	return wpa_auth->cb->send_eapol(wpa_auth->cb_ctx, addr, data, data_len,
164346981Scy					encrypt);
165214501Srpaulo}
166214501Srpaulo
167214501Srpaulo
168281806Srpaulo#ifdef CONFIG_MESH
169281806Srpaulostatic inline int wpa_auth_start_ampe(struct wpa_authenticator *wpa_auth,
170281806Srpaulo				      const u8 *addr)
171281806Srpaulo{
172346981Scy	if (wpa_auth->cb->start_ampe == NULL)
173281806Srpaulo		return -1;
174346981Scy	return wpa_auth->cb->start_ampe(wpa_auth->cb_ctx, addr);
175281806Srpaulo}
176281806Srpaulo#endif /* CONFIG_MESH */
177281806Srpaulo
178281806Srpaulo
179214501Srpauloint wpa_auth_for_each_sta(struct wpa_authenticator *wpa_auth,
180214501Srpaulo			  int (*cb)(struct wpa_state_machine *sm, void *ctx),
181214501Srpaulo			  void *cb_ctx)
182214501Srpaulo{
183346981Scy	if (wpa_auth->cb->for_each_sta == NULL)
184214501Srpaulo		return 0;
185346981Scy	return wpa_auth->cb->for_each_sta(wpa_auth->cb_ctx, cb, cb_ctx);
186214501Srpaulo}
187214501Srpaulo
188214501Srpaulo
189214501Srpauloint wpa_auth_for_each_auth(struct wpa_authenticator *wpa_auth,
190214501Srpaulo			   int (*cb)(struct wpa_authenticator *a, void *ctx),
191214501Srpaulo			   void *cb_ctx)
192214501Srpaulo{
193346981Scy	if (wpa_auth->cb->for_each_auth == NULL)
194214501Srpaulo		return 0;
195346981Scy	return wpa_auth->cb->for_each_auth(wpa_auth->cb_ctx, cb, cb_ctx);
196214501Srpaulo}
197214501Srpaulo
198214501Srpaulo
199214501Srpaulovoid wpa_auth_logger(struct wpa_authenticator *wpa_auth, const u8 *addr,
200214501Srpaulo		     logger_level level, const char *txt)
201214501Srpaulo{
202346981Scy	if (wpa_auth->cb->logger == NULL)
203214501Srpaulo		return;
204346981Scy	wpa_auth->cb->logger(wpa_auth->cb_ctx, addr, level, txt);
205214501Srpaulo}
206214501Srpaulo
207214501Srpaulo
208214501Srpaulovoid wpa_auth_vlogger(struct wpa_authenticator *wpa_auth, const u8 *addr,
209214501Srpaulo		      logger_level level, const char *fmt, ...)
210214501Srpaulo{
211214501Srpaulo	char *format;
212214501Srpaulo	int maxlen;
213214501Srpaulo	va_list ap;
214214501Srpaulo
215346981Scy	if (wpa_auth->cb->logger == NULL)
216214501Srpaulo		return;
217214501Srpaulo
218214501Srpaulo	maxlen = os_strlen(fmt) + 100;
219214501Srpaulo	format = os_malloc(maxlen);
220214501Srpaulo	if (!format)
221214501Srpaulo		return;
222214501Srpaulo
223214501Srpaulo	va_start(ap, fmt);
224214501Srpaulo	vsnprintf(format, maxlen, fmt, ap);
225214501Srpaulo	va_end(ap);
226214501Srpaulo
227214501Srpaulo	wpa_auth_logger(wpa_auth, addr, level, format);
228214501Srpaulo
229214501Srpaulo	os_free(format);
230214501Srpaulo}
231214501Srpaulo
232214501Srpaulo
233214501Srpaulostatic void wpa_sta_disconnect(struct wpa_authenticator *wpa_auth,
234346981Scy			       const u8 *addr, u16 reason)
235214501Srpaulo{
236346981Scy	if (wpa_auth->cb->disconnect == NULL)
237214501Srpaulo		return;
238346981Scy	wpa_printf(MSG_DEBUG, "wpa_sta_disconnect STA " MACSTR " (reason %u)",
239346981Scy		   MAC2STR(addr), reason);
240346981Scy	wpa_auth->cb->disconnect(wpa_auth->cb_ctx, addr, reason);
241214501Srpaulo}
242214501Srpaulo
243214501Srpaulo
244346981Scy#ifdef CONFIG_OCV
245346981Scystatic int wpa_channel_info(struct wpa_authenticator *wpa_auth,
246346981Scy			    struct wpa_channel_info *ci)
247214501Srpaulo{
248346981Scy	if (!wpa_auth->cb->channel_info)
249346981Scy		return -1;
250346981Scy	return wpa_auth->cb->channel_info(wpa_auth->cb_ctx, ci);
251214501Srpaulo}
252346981Scy#endif /* CONFIG_OCV */
253214501Srpaulo
254214501Srpaulo
255346981Scystatic int wpa_auth_update_vlan(struct wpa_authenticator *wpa_auth,
256346981Scy				const u8 *addr, int vlan_id)
257346981Scy{
258346981Scy	if (!wpa_auth->cb->update_vlan)
259346981Scy		return -1;
260346981Scy	return wpa_auth->cb->update_vlan(wpa_auth->cb_ctx, addr, vlan_id);
261346981Scy}
262346981Scy
263346981Scy
264214501Srpaulostatic void wpa_rekey_gmk(void *eloop_ctx, void *timeout_ctx)
265214501Srpaulo{
266214501Srpaulo	struct wpa_authenticator *wpa_auth = eloop_ctx;
267214501Srpaulo
268252726Srpaulo	if (random_get_bytes(wpa_auth->group->GMK, WPA_GMK_LEN)) {
269214501Srpaulo		wpa_printf(MSG_ERROR, "Failed to get random data for WPA "
270214501Srpaulo			   "initialization.");
271214501Srpaulo	} else {
272214501Srpaulo		wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "GMK rekeyd");
273252726Srpaulo		wpa_hexdump_key(MSG_DEBUG, "GMK",
274252726Srpaulo				wpa_auth->group->GMK, WPA_GMK_LEN);
275214501Srpaulo	}
276214501Srpaulo
277214501Srpaulo	if (wpa_auth->conf.wpa_gmk_rekey) {
278214501Srpaulo		eloop_register_timeout(wpa_auth->conf.wpa_gmk_rekey, 0,
279214501Srpaulo				       wpa_rekey_gmk, wpa_auth, NULL);
280214501Srpaulo	}
281214501Srpaulo}
282214501Srpaulo
283214501Srpaulo
284214501Srpaulostatic void wpa_rekey_gtk(void *eloop_ctx, void *timeout_ctx)
285214501Srpaulo{
286214501Srpaulo	struct wpa_authenticator *wpa_auth = eloop_ctx;
287289549Srpaulo	struct wpa_group *group, *next;
288214501Srpaulo
289214501Srpaulo	wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "rekeying GTK");
290289549Srpaulo	group = wpa_auth->group;
291289549Srpaulo	while (group) {
292289549Srpaulo		wpa_group_get(wpa_auth, group);
293289549Srpaulo
294214501Srpaulo		group->GTKReKey = TRUE;
295214501Srpaulo		do {
296214501Srpaulo			group->changed = FALSE;
297214501Srpaulo			wpa_group_sm_step(wpa_auth, group);
298214501Srpaulo		} while (group->changed);
299289549Srpaulo
300289549Srpaulo		next = group->next;
301289549Srpaulo		wpa_group_put(wpa_auth, group);
302289549Srpaulo		group = next;
303214501Srpaulo	}
304214501Srpaulo
305214501Srpaulo	if (wpa_auth->conf.wpa_group_rekey) {
306214501Srpaulo		eloop_register_timeout(wpa_auth->conf.wpa_group_rekey,
307214501Srpaulo				       0, wpa_rekey_gtk, wpa_auth, NULL);
308214501Srpaulo	}
309214501Srpaulo}
310214501Srpaulo
311214501Srpaulo
312214501Srpaulostatic void wpa_rekey_ptk(void *eloop_ctx, void *timeout_ctx)
313214501Srpaulo{
314214501Srpaulo	struct wpa_authenticator *wpa_auth = eloop_ctx;
315214501Srpaulo	struct wpa_state_machine *sm = timeout_ctx;
316214501Srpaulo
317214501Srpaulo	wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "rekeying PTK");
318214501Srpaulo	wpa_request_new_ptk(sm);
319214501Srpaulo	wpa_sm_step(sm);
320214501Srpaulo}
321214501Srpaulo
322214501Srpaulo
323346981Scyvoid wpa_auth_set_ptk_rekey_timer(struct wpa_state_machine *sm)
324346981Scy{
325346981Scy	if (sm && sm->wpa_auth->conf.wpa_ptk_rekey) {
326346981Scy		wpa_printf(MSG_DEBUG, "WPA: Start PTK rekeying timer for "
327346981Scy			   MACSTR " (%d seconds)", MAC2STR(sm->addr),
328346981Scy			   sm->wpa_auth->conf.wpa_ptk_rekey);
329346981Scy		eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm);
330346981Scy		eloop_register_timeout(sm->wpa_auth->conf.wpa_ptk_rekey, 0,
331346981Scy				       wpa_rekey_ptk, sm->wpa_auth, sm);
332346981Scy	}
333346981Scy}
334346981Scy
335346981Scy
336214501Srpaulostatic int wpa_auth_pmksa_clear_cb(struct wpa_state_machine *sm, void *ctx)
337214501Srpaulo{
338214501Srpaulo	if (sm->pmksa == ctx)
339214501Srpaulo		sm->pmksa = NULL;
340214501Srpaulo	return 0;
341214501Srpaulo}
342214501Srpaulo
343214501Srpaulo
344214501Srpaulostatic void wpa_auth_pmksa_free_cb(struct rsn_pmksa_cache_entry *entry,
345214501Srpaulo				   void *ctx)
346214501Srpaulo{
347214501Srpaulo	struct wpa_authenticator *wpa_auth = ctx;
348214501Srpaulo	wpa_auth_for_each_sta(wpa_auth, wpa_auth_pmksa_clear_cb, entry);
349214501Srpaulo}
350214501Srpaulo
351214501Srpaulo
352252726Srpaulostatic int wpa_group_init_gmk_and_counter(struct wpa_authenticator *wpa_auth,
353252726Srpaulo					  struct wpa_group *group)
354214501Srpaulo{
355281806Srpaulo	u8 buf[ETH_ALEN + 8 + sizeof(unsigned long)];
356252726Srpaulo	u8 rkey[32];
357281806Srpaulo	unsigned long ptr;
358252726Srpaulo
359252726Srpaulo	if (random_get_bytes(group->GMK, WPA_GMK_LEN) < 0)
360252726Srpaulo		return -1;
361252726Srpaulo	wpa_hexdump_key(MSG_DEBUG, "GMK", group->GMK, WPA_GMK_LEN);
362252726Srpaulo
363252726Srpaulo	/*
364252726Srpaulo	 * Counter = PRF-256(Random number, "Init Counter",
365252726Srpaulo	 *                   Local MAC Address || Time)
366252726Srpaulo	 */
367252726Srpaulo	os_memcpy(buf, wpa_auth->addr, ETH_ALEN);
368252726Srpaulo	wpa_get_ntp_timestamp(buf + ETH_ALEN);
369281806Srpaulo	ptr = (unsigned long) group;
370281806Srpaulo	os_memcpy(buf + ETH_ALEN + 8, &ptr, sizeof(ptr));
371346981Scy#ifdef TEST_FUZZ
372346981Scy	os_memset(buf + ETH_ALEN, 0xab, 8);
373346981Scy	os_memset(buf + ETH_ALEN + 8, 0xcd, sizeof(ptr));
374346981Scy#endif /* TEST_FUZZ */
375252726Srpaulo	if (random_get_bytes(rkey, sizeof(rkey)) < 0)
376252726Srpaulo		return -1;
377252726Srpaulo
378252726Srpaulo	if (sha1_prf(rkey, sizeof(rkey), "Init Counter", buf, sizeof(buf),
379252726Srpaulo		     group->Counter, WPA_NONCE_LEN) < 0)
380252726Srpaulo		return -1;
381252726Srpaulo	wpa_hexdump_key(MSG_DEBUG, "Key Counter",
382252726Srpaulo			group->Counter, WPA_NONCE_LEN);
383252726Srpaulo
384252726Srpaulo	return 0;
385214501Srpaulo}
386214501Srpaulo
387214501Srpaulo
388214501Srpaulostatic struct wpa_group * wpa_group_init(struct wpa_authenticator *wpa_auth,
389252726Srpaulo					 int vlan_id, int delay_init)
390214501Srpaulo{
391214501Srpaulo	struct wpa_group *group;
392214501Srpaulo
393214501Srpaulo	group = os_zalloc(sizeof(struct wpa_group));
394214501Srpaulo	if (group == NULL)
395214501Srpaulo		return NULL;
396214501Srpaulo
397214501Srpaulo	group->GTKAuthenticator = TRUE;
398214501Srpaulo	group->vlan_id = vlan_id;
399252726Srpaulo	group->GTK_len = wpa_cipher_key_len(wpa_auth->conf.wpa_group);
400214501Srpaulo
401252726Srpaulo	if (random_pool_ready() != 1) {
402252726Srpaulo		wpa_printf(MSG_INFO, "WPA: Not enough entropy in random pool "
403252726Srpaulo			   "for secure operations - update keys later when "
404252726Srpaulo			   "the first station connects");
405252726Srpaulo	}
406214501Srpaulo
407252726Srpaulo	/*
408252726Srpaulo	 * Set initial GMK/Counter value here. The actual values that will be
409252726Srpaulo	 * used in negotiations will be set once the first station tries to
410252726Srpaulo	 * connect. This allows more time for collecting additional randomness
411252726Srpaulo	 * on embedded devices.
412214501Srpaulo	 */
413252726Srpaulo	if (wpa_group_init_gmk_and_counter(wpa_auth, group) < 0) {
414214501Srpaulo		wpa_printf(MSG_ERROR, "Failed to get random data for WPA "
415214501Srpaulo			   "initialization.");
416214501Srpaulo		os_free(group);
417214501Srpaulo		return NULL;
418214501Srpaulo	}
419214501Srpaulo
420214501Srpaulo	group->GInit = TRUE;
421252726Srpaulo	if (delay_init) {
422252726Srpaulo		wpa_printf(MSG_DEBUG, "WPA: Delay group state machine start "
423252726Srpaulo			   "until Beacon frames have been configured");
424252726Srpaulo		/* Initialization is completed in wpa_init_keys(). */
425252726Srpaulo	} else {
426252726Srpaulo		wpa_group_sm_step(wpa_auth, group);
427252726Srpaulo		group->GInit = FALSE;
428252726Srpaulo		wpa_group_sm_step(wpa_auth, group);
429252726Srpaulo	}
430214501Srpaulo
431214501Srpaulo	return group;
432214501Srpaulo}
433214501Srpaulo
434214501Srpaulo
435214501Srpaulo/**
436214501Srpaulo * wpa_init - Initialize WPA authenticator
437214501Srpaulo * @addr: Authenticator address
438214501Srpaulo * @conf: Configuration for WPA authenticator
439214501Srpaulo * @cb: Callback functions for WPA authenticator
440214501Srpaulo * Returns: Pointer to WPA authenticator data or %NULL on failure
441214501Srpaulo */
442214501Srpaulostruct wpa_authenticator * wpa_init(const u8 *addr,
443214501Srpaulo				    struct wpa_auth_config *conf,
444346981Scy				    const struct wpa_auth_callbacks *cb,
445346981Scy				    void *cb_ctx)
446214501Srpaulo{
447214501Srpaulo	struct wpa_authenticator *wpa_auth;
448214501Srpaulo
449214501Srpaulo	wpa_auth = os_zalloc(sizeof(struct wpa_authenticator));
450214501Srpaulo	if (wpa_auth == NULL)
451214501Srpaulo		return NULL;
452214501Srpaulo	os_memcpy(wpa_auth->addr, addr, ETH_ALEN);
453214501Srpaulo	os_memcpy(&wpa_auth->conf, conf, sizeof(*conf));
454346981Scy	wpa_auth->cb = cb;
455346981Scy	wpa_auth->cb_ctx = cb_ctx;
456214501Srpaulo
457214501Srpaulo	if (wpa_auth_gen_wpa_ie(wpa_auth)) {
458214501Srpaulo		wpa_printf(MSG_ERROR, "Could not generate WPA IE.");
459214501Srpaulo		os_free(wpa_auth);
460214501Srpaulo		return NULL;
461214501Srpaulo	}
462214501Srpaulo
463252726Srpaulo	wpa_auth->group = wpa_group_init(wpa_auth, 0, 1);
464214501Srpaulo	if (wpa_auth->group == NULL) {
465214501Srpaulo		os_free(wpa_auth->wpa_ie);
466214501Srpaulo		os_free(wpa_auth);
467214501Srpaulo		return NULL;
468214501Srpaulo	}
469214501Srpaulo
470214501Srpaulo	wpa_auth->pmksa = pmksa_cache_auth_init(wpa_auth_pmksa_free_cb,
471214501Srpaulo						wpa_auth);
472214501Srpaulo	if (wpa_auth->pmksa == NULL) {
473214501Srpaulo		wpa_printf(MSG_ERROR, "PMKSA cache initialization failed.");
474281806Srpaulo		os_free(wpa_auth->group);
475214501Srpaulo		os_free(wpa_auth->wpa_ie);
476214501Srpaulo		os_free(wpa_auth);
477214501Srpaulo		return NULL;
478214501Srpaulo	}
479214501Srpaulo
480346981Scy#ifdef CONFIG_IEEE80211R_AP
481214501Srpaulo	wpa_auth->ft_pmk_cache = wpa_ft_pmk_cache_init();
482214501Srpaulo	if (wpa_auth->ft_pmk_cache == NULL) {
483214501Srpaulo		wpa_printf(MSG_ERROR, "FT PMK cache initialization failed.");
484281806Srpaulo		os_free(wpa_auth->group);
485214501Srpaulo		os_free(wpa_auth->wpa_ie);
486214501Srpaulo		pmksa_cache_auth_deinit(wpa_auth->pmksa);
487214501Srpaulo		os_free(wpa_auth);
488214501Srpaulo		return NULL;
489214501Srpaulo	}
490346981Scy#endif /* CONFIG_IEEE80211R_AP */
491214501Srpaulo
492214501Srpaulo	if (wpa_auth->conf.wpa_gmk_rekey) {
493214501Srpaulo		eloop_register_timeout(wpa_auth->conf.wpa_gmk_rekey, 0,
494214501Srpaulo				       wpa_rekey_gmk, wpa_auth, NULL);
495214501Srpaulo	}
496214501Srpaulo
497214501Srpaulo	if (wpa_auth->conf.wpa_group_rekey) {
498214501Srpaulo		eloop_register_timeout(wpa_auth->conf.wpa_group_rekey, 0,
499214501Srpaulo				       wpa_rekey_gtk, wpa_auth, NULL);
500214501Srpaulo	}
501214501Srpaulo
502281806Srpaulo#ifdef CONFIG_P2P
503281806Srpaulo	if (WPA_GET_BE32(conf->ip_addr_start)) {
504281806Srpaulo		int count = WPA_GET_BE32(conf->ip_addr_end) -
505281806Srpaulo			WPA_GET_BE32(conf->ip_addr_start) + 1;
506281806Srpaulo		if (count > 1000)
507281806Srpaulo			count = 1000;
508281806Srpaulo		if (count > 0)
509281806Srpaulo			wpa_auth->ip_pool = bitfield_alloc(count);
510281806Srpaulo	}
511281806Srpaulo#endif /* CONFIG_P2P */
512281806Srpaulo
513214501Srpaulo	return wpa_auth;
514214501Srpaulo}
515214501Srpaulo
516214501Srpaulo
517252726Srpauloint wpa_init_keys(struct wpa_authenticator *wpa_auth)
518252726Srpaulo{
519252726Srpaulo	struct wpa_group *group = wpa_auth->group;
520252726Srpaulo
521252726Srpaulo	wpa_printf(MSG_DEBUG, "WPA: Start group state machine to set initial "
522252726Srpaulo		   "keys");
523252726Srpaulo	wpa_group_sm_step(wpa_auth, group);
524252726Srpaulo	group->GInit = FALSE;
525252726Srpaulo	wpa_group_sm_step(wpa_auth, group);
526281806Srpaulo	if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
527281806Srpaulo		return -1;
528252726Srpaulo	return 0;
529252726Srpaulo}
530252726Srpaulo
531252726Srpaulo
532214501Srpaulo/**
533214501Srpaulo * wpa_deinit - Deinitialize WPA authenticator
534214501Srpaulo * @wpa_auth: Pointer to WPA authenticator data from wpa_init()
535214501Srpaulo */
536214501Srpaulovoid wpa_deinit(struct wpa_authenticator *wpa_auth)
537214501Srpaulo{
538214501Srpaulo	struct wpa_group *group, *prev;
539214501Srpaulo
540214501Srpaulo	eloop_cancel_timeout(wpa_rekey_gmk, wpa_auth, NULL);
541214501Srpaulo	eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL);
542214501Srpaulo
543214501Srpaulo	pmksa_cache_auth_deinit(wpa_auth->pmksa);
544214501Srpaulo
545346981Scy#ifdef CONFIG_IEEE80211R_AP
546214501Srpaulo	wpa_ft_pmk_cache_deinit(wpa_auth->ft_pmk_cache);
547214501Srpaulo	wpa_auth->ft_pmk_cache = NULL;
548346981Scy	wpa_ft_deinit(wpa_auth);
549346981Scy#endif /* CONFIG_IEEE80211R_AP */
550214501Srpaulo
551281806Srpaulo#ifdef CONFIG_P2P
552281806Srpaulo	bitfield_free(wpa_auth->ip_pool);
553281806Srpaulo#endif /* CONFIG_P2P */
554281806Srpaulo
555281806Srpaulo
556214501Srpaulo	os_free(wpa_auth->wpa_ie);
557214501Srpaulo
558214501Srpaulo	group = wpa_auth->group;
559214501Srpaulo	while (group) {
560214501Srpaulo		prev = group;
561214501Srpaulo		group = group->next;
562214501Srpaulo		os_free(prev);
563214501Srpaulo	}
564214501Srpaulo
565214501Srpaulo	os_free(wpa_auth);
566214501Srpaulo}
567214501Srpaulo
568214501Srpaulo
569214501Srpaulo/**
570214501Srpaulo * wpa_reconfig - Update WPA authenticator configuration
571214501Srpaulo * @wpa_auth: Pointer to WPA authenticator data from wpa_init()
572214501Srpaulo * @conf: Configuration for WPA authenticator
573214501Srpaulo */
574214501Srpauloint wpa_reconfig(struct wpa_authenticator *wpa_auth,
575214501Srpaulo		 struct wpa_auth_config *conf)
576214501Srpaulo{
577214501Srpaulo	struct wpa_group *group;
578214501Srpaulo	if (wpa_auth == NULL)
579214501Srpaulo		return 0;
580214501Srpaulo
581214501Srpaulo	os_memcpy(&wpa_auth->conf, conf, sizeof(*conf));
582214501Srpaulo	if (wpa_auth_gen_wpa_ie(wpa_auth)) {
583214501Srpaulo		wpa_printf(MSG_ERROR, "Could not generate WPA IE.");
584214501Srpaulo		return -1;
585214501Srpaulo	}
586214501Srpaulo
587214501Srpaulo	/*
588214501Srpaulo	 * Reinitialize GTK to make sure it is suitable for the new
589214501Srpaulo	 * configuration.
590214501Srpaulo	 */
591214501Srpaulo	group = wpa_auth->group;
592252726Srpaulo	group->GTK_len = wpa_cipher_key_len(wpa_auth->conf.wpa_group);
593214501Srpaulo	group->GInit = TRUE;
594214501Srpaulo	wpa_group_sm_step(wpa_auth, group);
595214501Srpaulo	group->GInit = FALSE;
596214501Srpaulo	wpa_group_sm_step(wpa_auth, group);
597214501Srpaulo
598214501Srpaulo	return 0;
599214501Srpaulo}
600214501Srpaulo
601214501Srpaulo
602214501Srpaulostruct wpa_state_machine *
603281806Srpaulowpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr,
604281806Srpaulo		  const u8 *p2p_dev_addr)
605214501Srpaulo{
606214501Srpaulo	struct wpa_state_machine *sm;
607214501Srpaulo
608281806Srpaulo	if (wpa_auth->group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
609281806Srpaulo		return NULL;
610281806Srpaulo
611214501Srpaulo	sm = os_zalloc(sizeof(struct wpa_state_machine));
612214501Srpaulo	if (sm == NULL)
613214501Srpaulo		return NULL;
614214501Srpaulo	os_memcpy(sm->addr, addr, ETH_ALEN);
615281806Srpaulo	if (p2p_dev_addr)
616281806Srpaulo		os_memcpy(sm->p2p_dev_addr, p2p_dev_addr, ETH_ALEN);
617214501Srpaulo
618214501Srpaulo	sm->wpa_auth = wpa_auth;
619214501Srpaulo	sm->group = wpa_auth->group;
620289549Srpaulo	wpa_group_get(sm->wpa_auth, sm->group);
621214501Srpaulo
622214501Srpaulo	return sm;
623214501Srpaulo}
624214501Srpaulo
625214501Srpaulo
626214501Srpauloint wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth,
627214501Srpaulo			    struct wpa_state_machine *sm)
628214501Srpaulo{
629214501Srpaulo	if (wpa_auth == NULL || !wpa_auth->conf.wpa || sm == NULL)
630214501Srpaulo		return -1;
631214501Srpaulo
632346981Scy#ifdef CONFIG_IEEE80211R_AP
633214501Srpaulo	if (sm->ft_completed) {
634214501Srpaulo		wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
635214501Srpaulo				"FT authentication already completed - do not "
636214501Srpaulo				"start 4-way handshake");
637281806Srpaulo		/* Go to PTKINITDONE state to allow GTK rekeying */
638281806Srpaulo		sm->wpa_ptk_state = WPA_PTK_PTKINITDONE;
639346981Scy		sm->Pair = TRUE;
640214501Srpaulo		return 0;
641214501Srpaulo	}
642346981Scy#endif /* CONFIG_IEEE80211R_AP */
643214501Srpaulo
644346981Scy#ifdef CONFIG_FILS
645346981Scy	if (sm->fils_completed) {
646346981Scy		wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
647346981Scy				"FILS authentication already completed - do not start 4-way handshake");
648346981Scy		/* Go to PTKINITDONE state to allow GTK rekeying */
649346981Scy		sm->wpa_ptk_state = WPA_PTK_PTKINITDONE;
650346981Scy		sm->Pair = TRUE;
651346981Scy		return 0;
652346981Scy	}
653346981Scy#endif /* CONFIG_FILS */
654346981Scy
655214501Srpaulo	if (sm->started) {
656214501Srpaulo		os_memset(&sm->key_replay, 0, sizeof(sm->key_replay));
657214501Srpaulo		sm->ReAuthenticationRequest = TRUE;
658214501Srpaulo		return wpa_sm_step(sm);
659214501Srpaulo	}
660214501Srpaulo
661214501Srpaulo	wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
662214501Srpaulo			"start authentication");
663214501Srpaulo	sm->started = 1;
664214501Srpaulo
665214501Srpaulo	sm->Init = TRUE;
666214501Srpaulo	if (wpa_sm_step(sm) == 1)
667214501Srpaulo		return 1; /* should not really happen */
668214501Srpaulo	sm->Init = FALSE;
669214501Srpaulo	sm->AuthenticationRequest = TRUE;
670214501Srpaulo	return wpa_sm_step(sm);
671214501Srpaulo}
672214501Srpaulo
673214501Srpaulo
674214501Srpaulovoid wpa_auth_sta_no_wpa(struct wpa_state_machine *sm)
675214501Srpaulo{
676214501Srpaulo	/* WPA/RSN was not used - clear WPA state. This is needed if the STA
677214501Srpaulo	 * reassociates back to the same AP while the previous entry for the
678214501Srpaulo	 * STA has not yet been removed. */
679214501Srpaulo	if (sm == NULL)
680214501Srpaulo		return;
681214501Srpaulo
682214501Srpaulo	sm->wpa_key_mgmt = 0;
683214501Srpaulo}
684214501Srpaulo
685214501Srpaulo
686214501Srpaulostatic void wpa_free_sta_sm(struct wpa_state_machine *sm)
687214501Srpaulo{
688281806Srpaulo#ifdef CONFIG_P2P
689281806Srpaulo	if (WPA_GET_BE32(sm->ip_addr)) {
690281806Srpaulo		u32 start;
691281806Srpaulo		wpa_printf(MSG_DEBUG, "P2P: Free assigned IP "
692281806Srpaulo			   "address %u.%u.%u.%u from " MACSTR,
693281806Srpaulo			   sm->ip_addr[0], sm->ip_addr[1],
694281806Srpaulo			   sm->ip_addr[2], sm->ip_addr[3],
695281806Srpaulo			   MAC2STR(sm->addr));
696281806Srpaulo		start = WPA_GET_BE32(sm->wpa_auth->conf.ip_addr_start);
697281806Srpaulo		bitfield_clear(sm->wpa_auth->ip_pool,
698281806Srpaulo			       WPA_GET_BE32(sm->ip_addr) - start);
699281806Srpaulo	}
700281806Srpaulo#endif /* CONFIG_P2P */
701252726Srpaulo	if (sm->GUpdateStationKeys) {
702252726Srpaulo		sm->group->GKeyDoneStations--;
703252726Srpaulo		sm->GUpdateStationKeys = FALSE;
704252726Srpaulo	}
705346981Scy#ifdef CONFIG_IEEE80211R_AP
706214501Srpaulo	os_free(sm->assoc_resp_ftie);
707281806Srpaulo	wpabuf_free(sm->ft_pending_req_ies);
708346981Scy#endif /* CONFIG_IEEE80211R_AP */
709214501Srpaulo	os_free(sm->last_rx_eapol_key);
710214501Srpaulo	os_free(sm->wpa_ie);
711289549Srpaulo	wpa_group_put(sm->wpa_auth, sm->group);
712346981Scy#ifdef CONFIG_DPP2
713346981Scy	wpabuf_clear_free(sm->dpp_z);
714346981Scy#endif /* CONFIG_DPP2 */
715346981Scy	bin_clear_free(sm, sizeof(*sm));
716214501Srpaulo}
717214501Srpaulo
718214501Srpaulo
719214501Srpaulovoid wpa_auth_sta_deinit(struct wpa_state_machine *sm)
720214501Srpaulo{
721214501Srpaulo	if (sm == NULL)
722214501Srpaulo		return;
723214501Srpaulo
724214501Srpaulo	if (sm->wpa_auth->conf.wpa_strict_rekey && sm->has_GTK) {
725214501Srpaulo		wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
726214501Srpaulo				"strict rekeying - force GTK rekey since STA "
727214501Srpaulo				"is leaving");
728346981Scy		if (eloop_deplete_timeout(0, 500000, wpa_rekey_gtk,
729346981Scy					  sm->wpa_auth, NULL) == -1)
730346981Scy			eloop_register_timeout(0, 500000, wpa_rekey_gtk, sm->wpa_auth,
731346981Scy					       NULL);
732214501Srpaulo	}
733214501Srpaulo
734214501Srpaulo	eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm);
735252726Srpaulo	sm->pending_1_of_4_timeout = 0;
736214501Srpaulo	eloop_cancel_timeout(wpa_sm_call_step, sm, NULL);
737214501Srpaulo	eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm);
738346981Scy#ifdef CONFIG_IEEE80211R_AP
739346981Scy	wpa_ft_sta_deinit(sm);
740346981Scy#endif /* CONFIG_IEEE80211R_AP */
741214501Srpaulo	if (sm->in_step_loop) {
742214501Srpaulo		/* Must not free state machine while wpa_sm_step() is running.
743214501Srpaulo		 * Freeing will be completed in the end of wpa_sm_step(). */
744214501Srpaulo		wpa_printf(MSG_DEBUG, "WPA: Registering pending STA state "
745214501Srpaulo			   "machine deinit for " MACSTR, MAC2STR(sm->addr));
746214501Srpaulo		sm->pending_deinit = 1;
747214501Srpaulo	} else
748214501Srpaulo		wpa_free_sta_sm(sm);
749214501Srpaulo}
750214501Srpaulo
751214501Srpaulo
752214501Srpaulostatic void wpa_request_new_ptk(struct wpa_state_machine *sm)
753214501Srpaulo{
754214501Srpaulo	if (sm == NULL)
755214501Srpaulo		return;
756214501Srpaulo
757214501Srpaulo	sm->PTKRequest = TRUE;
758214501Srpaulo	sm->PTK_valid = 0;
759214501Srpaulo}
760214501Srpaulo
761214501Srpaulo
762252726Srpaulostatic int wpa_replay_counter_valid(struct wpa_key_replay_counter *ctr,
763214501Srpaulo				    const u8 *replay_counter)
764214501Srpaulo{
765214501Srpaulo	int i;
766214501Srpaulo	for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) {
767252726Srpaulo		if (!ctr[i].valid)
768214501Srpaulo			break;
769252726Srpaulo		if (os_memcmp(replay_counter, ctr[i].counter,
770214501Srpaulo			      WPA_REPLAY_COUNTER_LEN) == 0)
771214501Srpaulo			return 1;
772214501Srpaulo	}
773214501Srpaulo	return 0;
774214501Srpaulo}
775214501Srpaulo
776214501Srpaulo
777252726Srpaulostatic void wpa_replay_counter_mark_invalid(struct wpa_key_replay_counter *ctr,
778252726Srpaulo					    const u8 *replay_counter)
779252726Srpaulo{
780252726Srpaulo	int i;
781252726Srpaulo	for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) {
782252726Srpaulo		if (ctr[i].valid &&
783252726Srpaulo		    (replay_counter == NULL ||
784252726Srpaulo		     os_memcmp(replay_counter, ctr[i].counter,
785252726Srpaulo			       WPA_REPLAY_COUNTER_LEN) == 0))
786252726Srpaulo			ctr[i].valid = FALSE;
787252726Srpaulo	}
788252726Srpaulo}
789252726Srpaulo
790252726Srpaulo
791346981Scy#ifdef CONFIG_IEEE80211R_AP
792214501Srpaulostatic int ft_check_msg_2_of_4(struct wpa_authenticator *wpa_auth,
793214501Srpaulo			       struct wpa_state_machine *sm,
794214501Srpaulo			       struct wpa_eapol_ie_parse *kde)
795214501Srpaulo{
796214501Srpaulo	struct wpa_ie_data ie;
797214501Srpaulo	struct rsn_mdie *mdie;
798214501Srpaulo
799214501Srpaulo	if (wpa_parse_wpa_ie_rsn(kde->rsn_ie, kde->rsn_ie_len, &ie) < 0 ||
800214501Srpaulo	    ie.num_pmkid != 1 || ie.pmkid == NULL) {
801214501Srpaulo		wpa_printf(MSG_DEBUG, "FT: No PMKR1Name in "
802214501Srpaulo			   "FT 4-way handshake message 2/4");
803214501Srpaulo		return -1;
804214501Srpaulo	}
805214501Srpaulo
806214501Srpaulo	os_memcpy(sm->sup_pmk_r1_name, ie.pmkid, PMKID_LEN);
807214501Srpaulo	wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from Supplicant",
808214501Srpaulo		    sm->sup_pmk_r1_name, PMKID_LEN);
809214501Srpaulo
810214501Srpaulo	if (!kde->mdie || !kde->ftie) {
811214501Srpaulo		wpa_printf(MSG_DEBUG, "FT: No %s in FT 4-way handshake "
812214501Srpaulo			   "message 2/4", kde->mdie ? "FTIE" : "MDIE");
813214501Srpaulo		return -1;
814214501Srpaulo	}
815214501Srpaulo
816214501Srpaulo	mdie = (struct rsn_mdie *) (kde->mdie + 2);
817214501Srpaulo	if (kde->mdie[1] < sizeof(struct rsn_mdie) ||
818214501Srpaulo	    os_memcmp(wpa_auth->conf.mobility_domain, mdie->mobility_domain,
819214501Srpaulo		      MOBILITY_DOMAIN_ID_LEN) != 0) {
820214501Srpaulo		wpa_printf(MSG_DEBUG, "FT: MDIE mismatch");
821214501Srpaulo		return -1;
822214501Srpaulo	}
823214501Srpaulo
824214501Srpaulo	if (sm->assoc_resp_ftie &&
825214501Srpaulo	    (kde->ftie[1] != sm->assoc_resp_ftie[1] ||
826214501Srpaulo	     os_memcmp(kde->ftie, sm->assoc_resp_ftie,
827214501Srpaulo		       2 + sm->assoc_resp_ftie[1]) != 0)) {
828214501Srpaulo		wpa_printf(MSG_DEBUG, "FT: FTIE mismatch");
829214501Srpaulo		wpa_hexdump(MSG_DEBUG, "FT: FTIE in EAPOL-Key msg 2/4",
830214501Srpaulo			    kde->ftie, kde->ftie_len);
831214501Srpaulo		wpa_hexdump(MSG_DEBUG, "FT: FTIE in (Re)AssocResp",
832214501Srpaulo			    sm->assoc_resp_ftie, 2 + sm->assoc_resp_ftie[1]);
833214501Srpaulo		return -1;
834214501Srpaulo	}
835214501Srpaulo
836214501Srpaulo	return 0;
837214501Srpaulo}
838346981Scy#endif /* CONFIG_IEEE80211R_AP */
839214501Srpaulo
840214501Srpaulo
841252726Srpaulostatic int wpa_receive_error_report(struct wpa_authenticator *wpa_auth,
842252726Srpaulo				    struct wpa_state_machine *sm, int group)
843252726Srpaulo{
844252726Srpaulo	/* Supplicant reported a Michael MIC error */
845252726Srpaulo	wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
846252726Srpaulo			 "received EAPOL-Key Error Request "
847252726Srpaulo			 "(STA detected Michael MIC failure (group=%d))",
848252726Srpaulo			 group);
849252726Srpaulo
850252726Srpaulo	if (group && wpa_auth->conf.wpa_group != WPA_CIPHER_TKIP) {
851252726Srpaulo		wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
852252726Srpaulo				"ignore Michael MIC failure report since "
853252726Srpaulo				"group cipher is not TKIP");
854252726Srpaulo	} else if (!group && sm->pairwise != WPA_CIPHER_TKIP) {
855252726Srpaulo		wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
856252726Srpaulo				"ignore Michael MIC failure report since "
857252726Srpaulo				"pairwise cipher is not TKIP");
858252726Srpaulo	} else {
859252726Srpaulo		if (wpa_auth_mic_failure_report(wpa_auth, sm->addr) > 0)
860252726Srpaulo			return 1; /* STA entry was removed */
861252726Srpaulo		sm->dot11RSNAStatsTKIPRemoteMICFailures++;
862252726Srpaulo		wpa_auth->dot11RSNAStatsTKIPRemoteMICFailures++;
863252726Srpaulo	}
864252726Srpaulo
865252726Srpaulo	/*
866252726Srpaulo	 * Error report is not a request for a new key handshake, but since
867252726Srpaulo	 * Authenticator may do it, let's change the keys now anyway.
868252726Srpaulo	 */
869252726Srpaulo	wpa_request_new_ptk(sm);
870252726Srpaulo	return 0;
871252726Srpaulo}
872252726Srpaulo
873252726Srpaulo
874281806Srpaulostatic int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data,
875281806Srpaulo			      size_t data_len)
876281806Srpaulo{
877281806Srpaulo	struct wpa_ptk PTK;
878281806Srpaulo	int ok = 0;
879281806Srpaulo	const u8 *pmk = NULL;
880346981Scy	size_t pmk_len;
881346981Scy	int vlan_id = 0;
882281806Srpaulo
883346981Scy	os_memset(&PTK, 0, sizeof(PTK));
884281806Srpaulo	for (;;) {
885346981Scy		if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
886346981Scy		    !wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
887281806Srpaulo			pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr,
888346981Scy					       sm->p2p_dev_addr, pmk, &pmk_len,
889346981Scy					       &vlan_id);
890281806Srpaulo			if (pmk == NULL)
891281806Srpaulo				break;
892346981Scy#ifdef CONFIG_IEEE80211R_AP
893346981Scy			if (wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) {
894346981Scy				os_memcpy(sm->xxkey, pmk, pmk_len);
895346981Scy				sm->xxkey_len = pmk_len;
896346981Scy			}
897346981Scy#endif /* CONFIG_IEEE80211R_AP */
898337817Scy		} else {
899281806Srpaulo			pmk = sm->PMK;
900337817Scy			pmk_len = sm->pmk_len;
901337817Scy		}
902281806Srpaulo
903346981Scy		if (wpa_derive_ptk(sm, sm->alt_SNonce, pmk, pmk_len, &PTK) < 0)
904346981Scy			break;
905281806Srpaulo
906346981Scy		if (wpa_verify_key_mic(sm->wpa_key_mgmt, pmk_len, &PTK,
907346981Scy				       data, data_len) == 0) {
908346981Scy			if (sm->PMK != pmk) {
909346981Scy				os_memcpy(sm->PMK, pmk, pmk_len);
910346981Scy				sm->pmk_len = pmk_len;
911346981Scy			}
912281806Srpaulo			ok = 1;
913281806Srpaulo			break;
914281806Srpaulo		}
915281806Srpaulo
916346981Scy		if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
917346981Scy		    wpa_key_mgmt_sae(sm->wpa_key_mgmt))
918281806Srpaulo			break;
919281806Srpaulo	}
920281806Srpaulo
921281806Srpaulo	if (!ok) {
922281806Srpaulo		wpa_printf(MSG_DEBUG,
923281806Srpaulo			   "WPA: Earlier SNonce did not result in matching MIC");
924281806Srpaulo		return -1;
925281806Srpaulo	}
926281806Srpaulo
927281806Srpaulo	wpa_printf(MSG_DEBUG,
928281806Srpaulo		   "WPA: Earlier SNonce resulted in matching MIC");
929281806Srpaulo	sm->alt_snonce_valid = 0;
930346981Scy
931346981Scy	if (vlan_id && wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
932346981Scy	    wpa_auth_update_vlan(sm->wpa_auth, sm->addr, vlan_id) < 0)
933346981Scy		return -1;
934346981Scy
935281806Srpaulo	os_memcpy(sm->SNonce, sm->alt_SNonce, WPA_NONCE_LEN);
936281806Srpaulo	os_memcpy(&sm->PTK, &PTK, sizeof(PTK));
937351611Scy	forced_memzero(&PTK, sizeof(PTK));
938281806Srpaulo	sm->PTK_valid = TRUE;
939281806Srpaulo
940281806Srpaulo	return 0;
941281806Srpaulo}
942281806Srpaulo
943281806Srpaulo
944214501Srpaulovoid wpa_receive(struct wpa_authenticator *wpa_auth,
945214501Srpaulo		 struct wpa_state_machine *sm,
946214501Srpaulo		 u8 *data, size_t data_len)
947214501Srpaulo{
948214501Srpaulo	struct ieee802_1x_hdr *hdr;
949214501Srpaulo	struct wpa_eapol_key *key;
950214501Srpaulo	u16 key_info, key_data_length;
951346981Scy	enum { PAIRWISE_2, PAIRWISE_4, GROUP_2, REQUEST } msg;
952214501Srpaulo	char *msgtxt;
953214501Srpaulo	struct wpa_eapol_ie_parse kde;
954346981Scy	const u8 *key_data;
955346981Scy	size_t keyhdrlen, mic_len;
956346981Scy	u8 *mic;
957214501Srpaulo
958214501Srpaulo	if (wpa_auth == NULL || !wpa_auth->conf.wpa || sm == NULL)
959214501Srpaulo		return;
960346981Scy	wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL data", data, data_len);
961214501Srpaulo
962346981Scy	mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
963346981Scy	keyhdrlen = sizeof(*key) + mic_len + 2;
964281806Srpaulo
965346981Scy	if (data_len < sizeof(*hdr) + keyhdrlen) {
966346981Scy		wpa_printf(MSG_DEBUG, "WPA: Ignore too short EAPOL-Key frame");
967214501Srpaulo		return;
968346981Scy	}
969214501Srpaulo
970214501Srpaulo	hdr = (struct ieee802_1x_hdr *) data;
971214501Srpaulo	key = (struct wpa_eapol_key *) (hdr + 1);
972346981Scy	mic = (u8 *) (key + 1);
973214501Srpaulo	key_info = WPA_GET_BE16(key->key_info);
974346981Scy	key_data = mic + mic_len + 2;
975346981Scy	key_data_length = WPA_GET_BE16(mic + mic_len);
976252726Srpaulo	wpa_printf(MSG_DEBUG, "WPA: Received EAPOL-Key from " MACSTR
977346981Scy		   " key_info=0x%x type=%u mic_len=%u key_data_length=%u",
978346981Scy		   MAC2STR(sm->addr), key_info, key->type,
979346981Scy		   (unsigned int) mic_len, key_data_length);
980346981Scy	wpa_hexdump(MSG_MSGDUMP,
981346981Scy		    "WPA: EAPOL-Key header (ending before Key MIC)",
982346981Scy		    key, sizeof(*key));
983346981Scy	wpa_hexdump(MSG_MSGDUMP, "WPA: EAPOL-Key Key MIC",
984346981Scy		    mic, mic_len);
985281806Srpaulo	if (key_data_length > data_len - sizeof(*hdr) - keyhdrlen) {
986214501Srpaulo		wpa_printf(MSG_INFO, "WPA: Invalid EAPOL-Key frame - "
987214501Srpaulo			   "key_data overflow (%d > %lu)",
988214501Srpaulo			   key_data_length,
989214501Srpaulo			   (unsigned long) (data_len - sizeof(*hdr) -
990281806Srpaulo					    keyhdrlen));
991214501Srpaulo		return;
992214501Srpaulo	}
993214501Srpaulo
994214501Srpaulo	if (sm->wpa == WPA_VERSION_WPA2) {
995252726Srpaulo		if (key->type == EAPOL_KEY_TYPE_WPA) {
996252726Srpaulo			/*
997252726Srpaulo			 * Some deployed station implementations seem to send
998252726Srpaulo			 * msg 4/4 with incorrect type value in WPA2 mode.
999252726Srpaulo			 */
1000252726Srpaulo			wpa_printf(MSG_DEBUG, "Workaround: Allow EAPOL-Key "
1001252726Srpaulo				   "with unexpected WPA type in RSN mode");
1002252726Srpaulo		} else if (key->type != EAPOL_KEY_TYPE_RSN) {
1003214501Srpaulo			wpa_printf(MSG_DEBUG, "Ignore EAPOL-Key with "
1004214501Srpaulo				   "unexpected type %d in RSN mode",
1005214501Srpaulo				   key->type);
1006214501Srpaulo			return;
1007214501Srpaulo		}
1008214501Srpaulo	} else {
1009214501Srpaulo		if (key->type != EAPOL_KEY_TYPE_WPA) {
1010214501Srpaulo			wpa_printf(MSG_DEBUG, "Ignore EAPOL-Key with "
1011214501Srpaulo				   "unexpected type %d in WPA mode",
1012214501Srpaulo				   key->type);
1013214501Srpaulo			return;
1014214501Srpaulo		}
1015214501Srpaulo	}
1016214501Srpaulo
1017252726Srpaulo	wpa_hexdump(MSG_DEBUG, "WPA: Received Key Nonce", key->key_nonce,
1018252726Srpaulo		    WPA_NONCE_LEN);
1019252726Srpaulo	wpa_hexdump(MSG_DEBUG, "WPA: Received Replay Counter",
1020252726Srpaulo		    key->replay_counter, WPA_REPLAY_COUNTER_LEN);
1021252726Srpaulo
1022214501Srpaulo	/* FIX: verify that the EAPOL-Key frame was encrypted if pairwise keys
1023214501Srpaulo	 * are set */
1024214501Srpaulo
1025346981Scy	if (key_info & WPA_KEY_INFO_SMK_MESSAGE) {
1026346981Scy		wpa_printf(MSG_DEBUG, "WPA: Ignore SMK message");
1027346981Scy		return;
1028346981Scy	}
1029346981Scy
1030346981Scy	if (key_info & WPA_KEY_INFO_REQUEST) {
1031214501Srpaulo		msg = REQUEST;
1032214501Srpaulo		msgtxt = "Request";
1033214501Srpaulo	} else if (!(key_info & WPA_KEY_INFO_KEY_TYPE)) {
1034214501Srpaulo		msg = GROUP_2;
1035214501Srpaulo		msgtxt = "2/2 Group";
1036346981Scy	} else if (key_data_length == 0 ||
1037346981Scy		   (mic_len == 0 && (key_info & WPA_KEY_INFO_ENCR_KEY_DATA) &&
1038346981Scy		    key_data_length == AES_BLOCK_SIZE)) {
1039214501Srpaulo		msg = PAIRWISE_4;
1040214501Srpaulo		msgtxt = "4/4 Pairwise";
1041214501Srpaulo	} else {
1042214501Srpaulo		msg = PAIRWISE_2;
1043214501Srpaulo		msgtxt = "2/4 Pairwise";
1044214501Srpaulo	}
1045214501Srpaulo
1046214501Srpaulo	if (msg == REQUEST || msg == PAIRWISE_2 || msg == PAIRWISE_4 ||
1047214501Srpaulo	    msg == GROUP_2) {
1048214501Srpaulo		u16 ver = key_info & WPA_KEY_INFO_TYPE_MASK;
1049252726Srpaulo		if (sm->pairwise == WPA_CIPHER_CCMP ||
1050252726Srpaulo		    sm->pairwise == WPA_CIPHER_GCMP) {
1051346981Scy			if (wpa_use_cmac(sm->wpa_key_mgmt) &&
1052346981Scy			    !wpa_use_akm_defined(sm->wpa_key_mgmt) &&
1053214501Srpaulo			    ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) {
1054214501Srpaulo				wpa_auth_logger(wpa_auth, sm->addr,
1055214501Srpaulo						LOGGER_WARNING,
1056214501Srpaulo						"advertised support for "
1057214501Srpaulo						"AES-128-CMAC, but did not "
1058214501Srpaulo						"use it");
1059214501Srpaulo				return;
1060214501Srpaulo			}
1061214501Srpaulo
1062346981Scy			if (!wpa_use_cmac(sm->wpa_key_mgmt) &&
1063346981Scy			    !wpa_use_akm_defined(sm->wpa_key_mgmt) &&
1064214501Srpaulo			    ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
1065214501Srpaulo				wpa_auth_logger(wpa_auth, sm->addr,
1066214501Srpaulo						LOGGER_WARNING,
1067214501Srpaulo						"did not use HMAC-SHA1-AES "
1068252726Srpaulo						"with CCMP/GCMP");
1069214501Srpaulo				return;
1070214501Srpaulo			}
1071214501Srpaulo		}
1072281806Srpaulo
1073346981Scy		if (wpa_use_akm_defined(sm->wpa_key_mgmt) &&
1074281806Srpaulo		    ver != WPA_KEY_INFO_TYPE_AKM_DEFINED) {
1075281806Srpaulo			wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING,
1076281806Srpaulo					"did not use EAPOL-Key descriptor version 0 as required for AKM-defined cases");
1077281806Srpaulo			return;
1078281806Srpaulo		}
1079214501Srpaulo	}
1080214501Srpaulo
1081214501Srpaulo	if (key_info & WPA_KEY_INFO_REQUEST) {
1082214501Srpaulo		if (sm->req_replay_counter_used &&
1083214501Srpaulo		    os_memcmp(key->replay_counter, sm->req_replay_counter,
1084214501Srpaulo			      WPA_REPLAY_COUNTER_LEN) <= 0) {
1085214501Srpaulo			wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING,
1086214501Srpaulo					"received EAPOL-Key request with "
1087214501Srpaulo					"replayed counter");
1088214501Srpaulo			return;
1089214501Srpaulo		}
1090214501Srpaulo	}
1091214501Srpaulo
1092214501Srpaulo	if (!(key_info & WPA_KEY_INFO_REQUEST) &&
1093252726Srpaulo	    !wpa_replay_counter_valid(sm->key_replay, key->replay_counter)) {
1094214501Srpaulo		int i;
1095252726Srpaulo
1096252726Srpaulo		if (msg == PAIRWISE_2 &&
1097252726Srpaulo		    wpa_replay_counter_valid(sm->prev_key_replay,
1098252726Srpaulo					     key->replay_counter) &&
1099252726Srpaulo		    sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING &&
1100252726Srpaulo		    os_memcmp(sm->SNonce, key->key_nonce, WPA_NONCE_LEN) != 0)
1101252726Srpaulo		{
1102252726Srpaulo			/*
1103252726Srpaulo			 * Some supplicant implementations (e.g., Windows XP
1104252726Srpaulo			 * WZC) update SNonce for each EAPOL-Key 2/4. This
1105252726Srpaulo			 * breaks the workaround on accepting any of the
1106252726Srpaulo			 * pending requests, so allow the SNonce to be updated
1107252726Srpaulo			 * even if we have already sent out EAPOL-Key 3/4.
1108252726Srpaulo			 */
1109252726Srpaulo			wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
1110252726Srpaulo					 "Process SNonce update from STA "
1111252726Srpaulo					 "based on retransmitted EAPOL-Key "
1112252726Srpaulo					 "1/4");
1113252726Srpaulo			sm->update_snonce = 1;
1114281806Srpaulo			os_memcpy(sm->alt_SNonce, sm->SNonce, WPA_NONCE_LEN);
1115281806Srpaulo			sm->alt_snonce_valid = TRUE;
1116281806Srpaulo			os_memcpy(sm->alt_replay_counter,
1117281806Srpaulo				  sm->key_replay[0].counter,
1118281806Srpaulo				  WPA_REPLAY_COUNTER_LEN);
1119252726Srpaulo			goto continue_processing;
1120252726Srpaulo		}
1121252726Srpaulo
1122281806Srpaulo		if (msg == PAIRWISE_4 && sm->alt_snonce_valid &&
1123281806Srpaulo		    sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING &&
1124281806Srpaulo		    os_memcmp(key->replay_counter, sm->alt_replay_counter,
1125281806Srpaulo			      WPA_REPLAY_COUNTER_LEN) == 0) {
1126281806Srpaulo			/*
1127281806Srpaulo			 * Supplicant may still be using the old SNonce since
1128281806Srpaulo			 * there was two EAPOL-Key 2/4 messages and they had
1129281806Srpaulo			 * different SNonce values.
1130281806Srpaulo			 */
1131281806Srpaulo			wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
1132281806Srpaulo					 "Try to process received EAPOL-Key 4/4 based on old Replay Counter and SNonce from an earlier EAPOL-Key 1/4");
1133281806Srpaulo			goto continue_processing;
1134281806Srpaulo		}
1135281806Srpaulo
1136252726Srpaulo		if (msg == PAIRWISE_2 &&
1137252726Srpaulo		    wpa_replay_counter_valid(sm->prev_key_replay,
1138252726Srpaulo					     key->replay_counter) &&
1139252726Srpaulo		    sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING) {
1140252726Srpaulo			wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
1141252726Srpaulo					 "ignore retransmitted EAPOL-Key %s - "
1142252726Srpaulo					 "SNonce did not change", msgtxt);
1143252726Srpaulo		} else {
1144252726Srpaulo			wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
1145252726Srpaulo					 "received EAPOL-Key %s with "
1146252726Srpaulo					 "unexpected replay counter", msgtxt);
1147252726Srpaulo		}
1148214501Srpaulo		for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) {
1149214501Srpaulo			if (!sm->key_replay[i].valid)
1150214501Srpaulo				break;
1151214501Srpaulo			wpa_hexdump(MSG_DEBUG, "pending replay counter",
1152214501Srpaulo				    sm->key_replay[i].counter,
1153214501Srpaulo				    WPA_REPLAY_COUNTER_LEN);
1154214501Srpaulo		}
1155214501Srpaulo		wpa_hexdump(MSG_DEBUG, "received replay counter",
1156214501Srpaulo			    key->replay_counter, WPA_REPLAY_COUNTER_LEN);
1157214501Srpaulo		return;
1158214501Srpaulo	}
1159214501Srpaulo
1160252726Srpaulocontinue_processing:
1161346981Scy#ifdef CONFIG_FILS
1162346981Scy	if (sm->wpa == WPA_VERSION_WPA2 && mic_len == 0 &&
1163346981Scy	    !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
1164346981Scy		wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
1165346981Scy				 "WPA: Encr Key Data bit not set even though AEAD cipher is supposed to be used - drop frame");
1166346981Scy		return;
1167346981Scy	}
1168346981Scy#endif /* CONFIG_FILS */
1169346981Scy
1170214501Srpaulo	switch (msg) {
1171214501Srpaulo	case PAIRWISE_2:
1172214501Srpaulo		if (sm->wpa_ptk_state != WPA_PTK_PTKSTART &&
1173252726Srpaulo		    sm->wpa_ptk_state != WPA_PTK_PTKCALCNEGOTIATING &&
1174252726Srpaulo		    (!sm->update_snonce ||
1175252726Srpaulo		     sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING)) {
1176214501Srpaulo			wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
1177214501Srpaulo					 "received EAPOL-Key msg 2/4 in "
1178214501Srpaulo					 "invalid state (%d) - dropped",
1179214501Srpaulo					 sm->wpa_ptk_state);
1180214501Srpaulo			return;
1181214501Srpaulo		}
1182252726Srpaulo		random_add_randomness(key->key_nonce, WPA_NONCE_LEN);
1183252726Srpaulo		if (sm->group->reject_4way_hs_for_entropy) {
1184252726Srpaulo			/*
1185252726Srpaulo			 * The system did not have enough entropy to generate
1186252726Srpaulo			 * strong random numbers. Reject the first 4-way
1187252726Srpaulo			 * handshake(s) and collect some entropy based on the
1188252726Srpaulo			 * information from it. Once enough entropy is
1189252726Srpaulo			 * available, the next atempt will trigger GMK/Key
1190252726Srpaulo			 * Counter update and the station will be allowed to
1191252726Srpaulo			 * continue.
1192252726Srpaulo			 */
1193252726Srpaulo			wpa_printf(MSG_DEBUG, "WPA: Reject 4-way handshake to "
1194252726Srpaulo				   "collect more entropy for random number "
1195252726Srpaulo				   "generation");
1196252726Srpaulo			random_mark_pool_ready();
1197346981Scy			wpa_sta_disconnect(wpa_auth, sm->addr,
1198346981Scy					   WLAN_REASON_PREV_AUTH_NOT_VALID);
1199252726Srpaulo			return;
1200252726Srpaulo		}
1201214501Srpaulo		break;
1202214501Srpaulo	case PAIRWISE_4:
1203214501Srpaulo		if (sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING ||
1204214501Srpaulo		    !sm->PTK_valid) {
1205214501Srpaulo			wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
1206214501Srpaulo					 "received EAPOL-Key msg 4/4 in "
1207214501Srpaulo					 "invalid state (%d) - dropped",
1208214501Srpaulo					 sm->wpa_ptk_state);
1209214501Srpaulo			return;
1210214501Srpaulo		}
1211214501Srpaulo		break;
1212214501Srpaulo	case GROUP_2:
1213214501Srpaulo		if (sm->wpa_ptk_group_state != WPA_PTK_GROUP_REKEYNEGOTIATING
1214214501Srpaulo		    || !sm->PTK_valid) {
1215214501Srpaulo			wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
1216214501Srpaulo					 "received EAPOL-Key msg 2/2 in "
1217214501Srpaulo					 "invalid state (%d) - dropped",
1218214501Srpaulo					 sm->wpa_ptk_group_state);
1219214501Srpaulo			return;
1220214501Srpaulo		}
1221214501Srpaulo		break;
1222214501Srpaulo	case REQUEST:
1223214501Srpaulo		break;
1224214501Srpaulo	}
1225214501Srpaulo
1226214501Srpaulo	wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
1227214501Srpaulo			 "received EAPOL-Key frame (%s)", msgtxt);
1228214501Srpaulo
1229214501Srpaulo	if (key_info & WPA_KEY_INFO_ACK) {
1230214501Srpaulo		wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
1231214501Srpaulo				"received invalid EAPOL-Key: Key Ack set");
1232214501Srpaulo		return;
1233214501Srpaulo	}
1234214501Srpaulo
1235346981Scy	if (!wpa_key_mgmt_fils(sm->wpa_key_mgmt) &&
1236346981Scy	    !(key_info & WPA_KEY_INFO_MIC)) {
1237214501Srpaulo		wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
1238214501Srpaulo				"received invalid EAPOL-Key: Key MIC not set");
1239214501Srpaulo		return;
1240214501Srpaulo	}
1241214501Srpaulo
1242346981Scy#ifdef CONFIG_FILS
1243346981Scy	if (wpa_key_mgmt_fils(sm->wpa_key_mgmt) &&
1244346981Scy	    (key_info & WPA_KEY_INFO_MIC)) {
1245346981Scy		wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
1246346981Scy				"received invalid EAPOL-Key: Key MIC set");
1247346981Scy		return;
1248346981Scy	}
1249346981Scy#endif /* CONFIG_FILS */
1250346981Scy
1251214501Srpaulo	sm->MICVerified = FALSE;
1252252726Srpaulo	if (sm->PTK_valid && !sm->update_snonce) {
1253346981Scy		if (mic_len &&
1254346981Scy		    wpa_verify_key_mic(sm->wpa_key_mgmt, sm->pmk_len, &sm->PTK,
1255346981Scy				       data, data_len) &&
1256281806Srpaulo		    (msg != PAIRWISE_4 || !sm->alt_snonce_valid ||
1257281806Srpaulo		     wpa_try_alt_snonce(sm, data, data_len))) {
1258214501Srpaulo			wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
1259214501Srpaulo					"received EAPOL-Key with invalid MIC");
1260346981Scy#ifdef TEST_FUZZ
1261346981Scy			wpa_printf(MSG_INFO,
1262346981Scy				   "TEST: Ignore Key MIC failure for fuzz testing");
1263346981Scy			goto continue_fuzz;
1264346981Scy#endif /* TEST_FUZZ */
1265214501Srpaulo			return;
1266214501Srpaulo		}
1267346981Scy#ifdef CONFIG_FILS
1268346981Scy		if (!mic_len &&
1269346981Scy		    wpa_aead_decrypt(sm, &sm->PTK, data, data_len,
1270346981Scy				     &key_data_length) < 0) {
1271346981Scy			wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
1272346981Scy					"received EAPOL-Key with invalid MIC");
1273346981Scy#ifdef TEST_FUZZ
1274346981Scy			wpa_printf(MSG_INFO,
1275346981Scy				   "TEST: Ignore Key MIC failure for fuzz testing");
1276346981Scy			goto continue_fuzz;
1277346981Scy#endif /* TEST_FUZZ */
1278346981Scy			return;
1279346981Scy		}
1280346981Scy#endif /* CONFIG_FILS */
1281346981Scy#ifdef TEST_FUZZ
1282346981Scy	continue_fuzz:
1283346981Scy#endif /* TEST_FUZZ */
1284214501Srpaulo		sm->MICVerified = TRUE;
1285214501Srpaulo		eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm);
1286252726Srpaulo		sm->pending_1_of_4_timeout = 0;
1287214501Srpaulo	}
1288214501Srpaulo
1289214501Srpaulo	if (key_info & WPA_KEY_INFO_REQUEST) {
1290214501Srpaulo		if (sm->MICVerified) {
1291214501Srpaulo			sm->req_replay_counter_used = 1;
1292214501Srpaulo			os_memcpy(sm->req_replay_counter, key->replay_counter,
1293214501Srpaulo				  WPA_REPLAY_COUNTER_LEN);
1294214501Srpaulo		} else {
1295214501Srpaulo			wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
1296214501Srpaulo					"received EAPOL-Key request with "
1297214501Srpaulo					"invalid MIC");
1298214501Srpaulo			return;
1299214501Srpaulo		}
1300214501Srpaulo
1301214501Srpaulo		/*
1302214501Srpaulo		 * TODO: should decrypt key data field if encryption was used;
1303214501Srpaulo		 * even though MAC address KDE is not normally encrypted,
1304214501Srpaulo		 * supplicant is allowed to encrypt it.
1305214501Srpaulo		 */
1306346981Scy		if (key_info & WPA_KEY_INFO_ERROR) {
1307252726Srpaulo			if (wpa_receive_error_report(
1308252726Srpaulo				    wpa_auth, sm,
1309252726Srpaulo				    !(key_info & WPA_KEY_INFO_KEY_TYPE)) > 0)
1310252726Srpaulo				return; /* STA entry was removed */
1311214501Srpaulo		} else if (key_info & WPA_KEY_INFO_KEY_TYPE) {
1312214501Srpaulo			wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
1313214501Srpaulo					"received EAPOL-Key Request for new "
1314214501Srpaulo					"4-Way Handshake");
1315214501Srpaulo			wpa_request_new_ptk(sm);
1316214501Srpaulo		} else if (key_data_length > 0 &&
1317281806Srpaulo			   wpa_parse_kde_ies(key_data, key_data_length,
1318281806Srpaulo					     &kde) == 0 &&
1319214501Srpaulo			   kde.mac_addr) {
1320214501Srpaulo		} else {
1321214501Srpaulo			wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
1322214501Srpaulo					"received EAPOL-Key Request for GTK "
1323214501Srpaulo					"rekeying");
1324214501Srpaulo			eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL);
1325214501Srpaulo			wpa_rekey_gtk(wpa_auth, NULL);
1326214501Srpaulo		}
1327214501Srpaulo	} else {
1328252726Srpaulo		/* Do not allow the same key replay counter to be reused. */
1329252726Srpaulo		wpa_replay_counter_mark_invalid(sm->key_replay,
1330252726Srpaulo						key->replay_counter);
1331252726Srpaulo
1332252726Srpaulo		if (msg == PAIRWISE_2) {
1333252726Srpaulo			/*
1334252726Srpaulo			 * Maintain a copy of the pending EAPOL-Key frames in
1335252726Srpaulo			 * case the EAPOL-Key frame was retransmitted. This is
1336252726Srpaulo			 * needed to allow EAPOL-Key msg 2/4 reply to another
1337252726Srpaulo			 * pending msg 1/4 to update the SNonce to work around
1338252726Srpaulo			 * unexpected supplicant behavior.
1339252726Srpaulo			 */
1340252726Srpaulo			os_memcpy(sm->prev_key_replay, sm->key_replay,
1341252726Srpaulo				  sizeof(sm->key_replay));
1342252726Srpaulo		} else {
1343252726Srpaulo			os_memset(sm->prev_key_replay, 0,
1344252726Srpaulo				  sizeof(sm->prev_key_replay));
1345252726Srpaulo		}
1346252726Srpaulo
1347252726Srpaulo		/*
1348252726Srpaulo		 * Make sure old valid counters are not accepted anymore and
1349252726Srpaulo		 * do not get copied again.
1350252726Srpaulo		 */
1351252726Srpaulo		wpa_replay_counter_mark_invalid(sm->key_replay, NULL);
1352214501Srpaulo	}
1353214501Srpaulo
1354214501Srpaulo	os_free(sm->last_rx_eapol_key);
1355346981Scy	sm->last_rx_eapol_key = os_memdup(data, data_len);
1356214501Srpaulo	if (sm->last_rx_eapol_key == NULL)
1357214501Srpaulo		return;
1358214501Srpaulo	sm->last_rx_eapol_key_len = data_len;
1359214501Srpaulo
1360252726Srpaulo	sm->rx_eapol_key_secure = !!(key_info & WPA_KEY_INFO_SECURE);
1361214501Srpaulo	sm->EAPOLKeyReceived = TRUE;
1362214501Srpaulo	sm->EAPOLKeyPairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE);
1363214501Srpaulo	sm->EAPOLKeyRequest = !!(key_info & WPA_KEY_INFO_REQUEST);
1364214501Srpaulo	os_memcpy(sm->SNonce, key->key_nonce, WPA_NONCE_LEN);
1365214501Srpaulo	wpa_sm_step(sm);
1366214501Srpaulo}
1367214501Srpaulo
1368214501Srpaulo
1369252726Srpaulostatic int wpa_gmk_to_gtk(const u8 *gmk, const char *label, const u8 *addr,
1370252726Srpaulo			  const u8 *gnonce, u8 *gtk, size_t gtk_len)
1371214501Srpaulo{
1372346981Scy	u8 data[ETH_ALEN + WPA_NONCE_LEN + 8 + WPA_GTK_MAX_LEN];
1373252726Srpaulo	u8 *pos;
1374252726Srpaulo	int ret = 0;
1375214501Srpaulo
1376252726Srpaulo	/* GTK = PRF-X(GMK, "Group key expansion",
1377252726Srpaulo	 *	AA || GNonce || Time || random data)
1378252726Srpaulo	 * The example described in the IEEE 802.11 standard uses only AA and
1379252726Srpaulo	 * GNonce as inputs here. Add some more entropy since this derivation
1380252726Srpaulo	 * is done only at the Authenticator and as such, does not need to be
1381252726Srpaulo	 * exactly same.
1382252726Srpaulo	 */
1383346981Scy	os_memset(data, 0, sizeof(data));
1384214501Srpaulo	os_memcpy(data, addr, ETH_ALEN);
1385214501Srpaulo	os_memcpy(data + ETH_ALEN, gnonce, WPA_NONCE_LEN);
1386252726Srpaulo	pos = data + ETH_ALEN + WPA_NONCE_LEN;
1387252726Srpaulo	wpa_get_ntp_timestamp(pos);
1388346981Scy#ifdef TEST_FUZZ
1389346981Scy	os_memset(pos, 0xef, 8);
1390346981Scy#endif /* TEST_FUZZ */
1391252726Srpaulo	pos += 8;
1392346981Scy	if (random_get_bytes(pos, gtk_len) < 0)
1393252726Srpaulo		ret = -1;
1394214501Srpaulo
1395346981Scy#ifdef CONFIG_SHA384
1396346981Scy	if (sha384_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data),
1397346981Scy		       gtk, gtk_len) < 0)
1398252726Srpaulo		ret = -1;
1399346981Scy#else /* CONFIG_SHA384 */
1400346981Scy#ifdef CONFIG_SHA256
1401346981Scy	if (sha256_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data),
1402346981Scy		       gtk, gtk_len) < 0)
1403346981Scy		ret = -1;
1404346981Scy#else /* CONFIG_SHA256 */
1405346981Scy	if (sha1_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data),
1406346981Scy		     gtk, gtk_len) < 0)
1407346981Scy		ret = -1;
1408346981Scy#endif /* CONFIG_SHA256 */
1409346981Scy#endif /* CONFIG_SHA384 */
1410214501Srpaulo
1411351611Scy	forced_memzero(data, sizeof(data));
1412351611Scy
1413252726Srpaulo	return ret;
1414214501Srpaulo}
1415214501Srpaulo
1416214501Srpaulo
1417214501Srpaulostatic void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx)
1418214501Srpaulo{
1419214501Srpaulo	struct wpa_authenticator *wpa_auth = eloop_ctx;
1420214501Srpaulo	struct wpa_state_machine *sm = timeout_ctx;
1421214501Srpaulo
1422252726Srpaulo	sm->pending_1_of_4_timeout = 0;
1423214501Srpaulo	wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "EAPOL-Key timeout");
1424214501Srpaulo	sm->TimeoutEvt = TRUE;
1425214501Srpaulo	wpa_sm_step(sm);
1426214501Srpaulo}
1427214501Srpaulo
1428214501Srpaulo
1429214501Srpaulovoid __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
1430214501Srpaulo		      struct wpa_state_machine *sm, int key_info,
1431214501Srpaulo		      const u8 *key_rsc, const u8 *nonce,
1432214501Srpaulo		      const u8 *kde, size_t kde_len,
1433214501Srpaulo		      int keyidx, int encr, int force_version)
1434214501Srpaulo{
1435214501Srpaulo	struct ieee802_1x_hdr *hdr;
1436214501Srpaulo	struct wpa_eapol_key *key;
1437281806Srpaulo	size_t len, mic_len, keyhdrlen;
1438214501Srpaulo	int alg;
1439214501Srpaulo	int key_data_len, pad_len = 0;
1440214501Srpaulo	u8 *buf, *pos;
1441214501Srpaulo	int version, pairwise;
1442214501Srpaulo	int i;
1443346981Scy	u8 *key_mic, *key_data;
1444214501Srpaulo
1445346981Scy	mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
1446346981Scy	keyhdrlen = sizeof(*key) + mic_len + 2;
1447214501Srpaulo
1448281806Srpaulo	len = sizeof(struct ieee802_1x_hdr) + keyhdrlen;
1449281806Srpaulo
1450214501Srpaulo	if (force_version)
1451214501Srpaulo		version = force_version;
1452346981Scy	else if (wpa_use_akm_defined(sm->wpa_key_mgmt))
1453281806Srpaulo		version = WPA_KEY_INFO_TYPE_AKM_DEFINED;
1454346981Scy	else if (wpa_use_cmac(sm->wpa_key_mgmt))
1455214501Srpaulo		version = WPA_KEY_INFO_TYPE_AES_128_CMAC;
1456252726Srpaulo	else if (sm->pairwise != WPA_CIPHER_TKIP)
1457214501Srpaulo		version = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;
1458214501Srpaulo	else
1459214501Srpaulo		version = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
1460214501Srpaulo
1461281806Srpaulo	pairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE);
1462214501Srpaulo
1463214501Srpaulo	wpa_printf(MSG_DEBUG, "WPA: Send EAPOL(version=%d secure=%d mic=%d "
1464214501Srpaulo		   "ack=%d install=%d pairwise=%d kde_len=%lu keyidx=%d "
1465214501Srpaulo		   "encr=%d)",
1466214501Srpaulo		   version,
1467214501Srpaulo		   (key_info & WPA_KEY_INFO_SECURE) ? 1 : 0,
1468214501Srpaulo		   (key_info & WPA_KEY_INFO_MIC) ? 1 : 0,
1469214501Srpaulo		   (key_info & WPA_KEY_INFO_ACK) ? 1 : 0,
1470214501Srpaulo		   (key_info & WPA_KEY_INFO_INSTALL) ? 1 : 0,
1471214501Srpaulo		   pairwise, (unsigned long) kde_len, keyidx, encr);
1472214501Srpaulo
1473214501Srpaulo	key_data_len = kde_len;
1474214501Srpaulo
1475214501Srpaulo	if ((version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
1476346981Scy	     wpa_use_aes_key_wrap(sm->wpa_key_mgmt) ||
1477214501Srpaulo	     version == WPA_KEY_INFO_TYPE_AES_128_CMAC) && encr) {
1478214501Srpaulo		pad_len = key_data_len % 8;
1479214501Srpaulo		if (pad_len)
1480214501Srpaulo			pad_len = 8 - pad_len;
1481214501Srpaulo		key_data_len += pad_len + 8;
1482214501Srpaulo	}
1483214501Srpaulo
1484214501Srpaulo	len += key_data_len;
1485346981Scy	if (!mic_len && encr)
1486346981Scy		len += AES_BLOCK_SIZE;
1487214501Srpaulo
1488214501Srpaulo	hdr = os_zalloc(len);
1489214501Srpaulo	if (hdr == NULL)
1490214501Srpaulo		return;
1491214501Srpaulo	hdr->version = wpa_auth->conf.eapol_version;
1492214501Srpaulo	hdr->type = IEEE802_1X_TYPE_EAPOL_KEY;
1493214501Srpaulo	hdr->length = host_to_be16(len  - sizeof(*hdr));
1494214501Srpaulo	key = (struct wpa_eapol_key *) (hdr + 1);
1495346981Scy	key_mic = (u8 *) (key + 1);
1496281806Srpaulo	key_data = ((u8 *) (hdr + 1)) + keyhdrlen;
1497214501Srpaulo
1498214501Srpaulo	key->type = sm->wpa == WPA_VERSION_WPA2 ?
1499214501Srpaulo		EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
1500214501Srpaulo	key_info |= version;
1501214501Srpaulo	if (encr && sm->wpa == WPA_VERSION_WPA2)
1502214501Srpaulo		key_info |= WPA_KEY_INFO_ENCR_KEY_DATA;
1503214501Srpaulo	if (sm->wpa != WPA_VERSION_WPA2)
1504214501Srpaulo		key_info |= keyidx << WPA_KEY_INFO_KEY_INDEX_SHIFT;
1505214501Srpaulo	WPA_PUT_BE16(key->key_info, key_info);
1506214501Srpaulo
1507214501Srpaulo	alg = pairwise ? sm->pairwise : wpa_auth->conf.wpa_group;
1508346981Scy	if (sm->wpa == WPA_VERSION_WPA2 && !pairwise)
1509214501Srpaulo		WPA_PUT_BE16(key->key_length, 0);
1510346981Scy	else
1511346981Scy		WPA_PUT_BE16(key->key_length, wpa_cipher_key_len(alg));
1512214501Srpaulo
1513214501Srpaulo	for (i = RSNA_MAX_EAPOL_RETRIES - 1; i > 0; i--) {
1514214501Srpaulo		sm->key_replay[i].valid = sm->key_replay[i - 1].valid;
1515214501Srpaulo		os_memcpy(sm->key_replay[i].counter,
1516214501Srpaulo			  sm->key_replay[i - 1].counter,
1517214501Srpaulo			  WPA_REPLAY_COUNTER_LEN);
1518214501Srpaulo	}
1519214501Srpaulo	inc_byte_array(sm->key_replay[0].counter, WPA_REPLAY_COUNTER_LEN);
1520214501Srpaulo	os_memcpy(key->replay_counter, sm->key_replay[0].counter,
1521214501Srpaulo		  WPA_REPLAY_COUNTER_LEN);
1522281806Srpaulo	wpa_hexdump(MSG_DEBUG, "WPA: Replay Counter",
1523281806Srpaulo		    key->replay_counter, WPA_REPLAY_COUNTER_LEN);
1524214501Srpaulo	sm->key_replay[0].valid = TRUE;
1525214501Srpaulo
1526214501Srpaulo	if (nonce)
1527214501Srpaulo		os_memcpy(key->key_nonce, nonce, WPA_NONCE_LEN);
1528214501Srpaulo
1529214501Srpaulo	if (key_rsc)
1530214501Srpaulo		os_memcpy(key->key_rsc, key_rsc, WPA_KEY_RSC_LEN);
1531214501Srpaulo
1532214501Srpaulo	if (kde && !encr) {
1533281806Srpaulo		os_memcpy(key_data, kde, kde_len);
1534346981Scy		WPA_PUT_BE16(key_mic + mic_len, kde_len);
1535346981Scy#ifdef CONFIG_FILS
1536346981Scy	} else if (!mic_len && kde) {
1537346981Scy		const u8 *aad[1];
1538346981Scy		size_t aad_len[1];
1539346981Scy
1540346981Scy		WPA_PUT_BE16(key_mic, AES_BLOCK_SIZE + kde_len);
1541346981Scy		wpa_hexdump_key(MSG_DEBUG, "Plaintext EAPOL-Key Key Data",
1542346981Scy				kde, kde_len);
1543346981Scy
1544346981Scy		wpa_hexdump_key(MSG_DEBUG, "WPA: KEK",
1545346981Scy				sm->PTK.kek, sm->PTK.kek_len);
1546346981Scy		/* AES-SIV AAD from EAPOL protocol version field (inclusive) to
1547346981Scy		 * to Key Data (exclusive). */
1548346981Scy		aad[0] = (u8 *) hdr;
1549346981Scy		aad_len[0] = key_mic + 2 - (u8 *) hdr;
1550346981Scy		if (aes_siv_encrypt(sm->PTK.kek, sm->PTK.kek_len, kde, kde_len,
1551346981Scy				    1, aad, aad_len, key_mic + 2) < 0) {
1552346981Scy			wpa_printf(MSG_DEBUG, "WPA: AES-SIV encryption failed");
1553346981Scy			return;
1554346981Scy		}
1555346981Scy
1556346981Scy		wpa_hexdump(MSG_DEBUG, "WPA: Encrypted Key Data from SIV",
1557346981Scy			    key_mic + 2, AES_BLOCK_SIZE + kde_len);
1558346981Scy#endif /* CONFIG_FILS */
1559214501Srpaulo	} else if (encr && kde) {
1560214501Srpaulo		buf = os_zalloc(key_data_len);
1561214501Srpaulo		if (buf == NULL) {
1562214501Srpaulo			os_free(hdr);
1563214501Srpaulo			return;
1564214501Srpaulo		}
1565214501Srpaulo		pos = buf;
1566214501Srpaulo		os_memcpy(pos, kde, kde_len);
1567214501Srpaulo		pos += kde_len;
1568214501Srpaulo
1569214501Srpaulo		if (pad_len)
1570214501Srpaulo			*pos++ = 0xdd;
1571214501Srpaulo
1572214501Srpaulo		wpa_hexdump_key(MSG_DEBUG, "Plaintext EAPOL-Key Key Data",
1573214501Srpaulo				buf, key_data_len);
1574214501Srpaulo		if (version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
1575346981Scy		    wpa_use_aes_key_wrap(sm->wpa_key_mgmt) ||
1576214501Srpaulo		    version == WPA_KEY_INFO_TYPE_AES_128_CMAC) {
1577346981Scy			wpa_printf(MSG_DEBUG,
1578346981Scy				   "WPA: Encrypt Key Data using AES-WRAP (KEK length %u)",
1579346981Scy				   (unsigned int) sm->PTK.kek_len);
1580281806Srpaulo			if (aes_wrap(sm->PTK.kek, sm->PTK.kek_len,
1581281806Srpaulo				     (key_data_len - 8) / 8, buf, key_data)) {
1582214501Srpaulo				os_free(hdr);
1583214501Srpaulo				os_free(buf);
1584214501Srpaulo				return;
1585214501Srpaulo			}
1586346981Scy			WPA_PUT_BE16(key_mic + mic_len, key_data_len);
1587289549Srpaulo#ifndef CONFIG_NO_RC4
1588281806Srpaulo		} else if (sm->PTK.kek_len == 16) {
1589214501Srpaulo			u8 ek[32];
1590346981Scy
1591346981Scy			wpa_printf(MSG_DEBUG,
1592346981Scy				   "WPA: Encrypt Key Data using RC4");
1593214501Srpaulo			os_memcpy(key->key_iv,
1594214501Srpaulo				  sm->group->Counter + WPA_NONCE_LEN - 16, 16);
1595214501Srpaulo			inc_byte_array(sm->group->Counter, WPA_NONCE_LEN);
1596214501Srpaulo			os_memcpy(ek, key->key_iv, 16);
1597281806Srpaulo			os_memcpy(ek + 16, sm->PTK.kek, sm->PTK.kek_len);
1598281806Srpaulo			os_memcpy(key_data, buf, key_data_len);
1599281806Srpaulo			rc4_skip(ek, 32, 256, key_data, key_data_len);
1600346981Scy			WPA_PUT_BE16(key_mic + mic_len, key_data_len);
1601289549Srpaulo#endif /* CONFIG_NO_RC4 */
1602281806Srpaulo		} else {
1603281806Srpaulo			os_free(hdr);
1604281806Srpaulo			os_free(buf);
1605281806Srpaulo			return;
1606214501Srpaulo		}
1607214501Srpaulo		os_free(buf);
1608214501Srpaulo	}
1609214501Srpaulo
1610214501Srpaulo	if (key_info & WPA_KEY_INFO_MIC) {
1611346981Scy		if (!sm->PTK_valid || !mic_len) {
1612214501Srpaulo			wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
1613214501Srpaulo					"PTK not valid when sending EAPOL-Key "
1614214501Srpaulo					"frame");
1615214501Srpaulo			os_free(hdr);
1616214501Srpaulo			return;
1617214501Srpaulo		}
1618281806Srpaulo
1619346981Scy		if (wpa_eapol_key_mic(sm->PTK.kck, sm->PTK.kck_len,
1620346981Scy				      sm->wpa_key_mgmt, version,
1621346981Scy				      (u8 *) hdr, len, key_mic) < 0) {
1622346981Scy			os_free(hdr);
1623346981Scy			return;
1624346981Scy		}
1625281806Srpaulo#ifdef CONFIG_TESTING_OPTIONS
1626281806Srpaulo		if (!pairwise &&
1627281806Srpaulo		    wpa_auth->conf.corrupt_gtk_rekey_mic_probability > 0.0 &&
1628281806Srpaulo		    drand48() <
1629281806Srpaulo		    wpa_auth->conf.corrupt_gtk_rekey_mic_probability) {
1630281806Srpaulo			wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
1631281806Srpaulo					"Corrupting group EAPOL-Key Key MIC");
1632281806Srpaulo			key_mic[0]++;
1633281806Srpaulo		}
1634281806Srpaulo#endif /* CONFIG_TESTING_OPTIONS */
1635214501Srpaulo	}
1636214501Srpaulo
1637214501Srpaulo	wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_inc_EapolFramesTx,
1638214501Srpaulo			   1);
1639214501Srpaulo	wpa_auth_send_eapol(wpa_auth, sm->addr, (u8 *) hdr, len,
1640214501Srpaulo			    sm->pairwise_set);
1641214501Srpaulo	os_free(hdr);
1642214501Srpaulo}
1643214501Srpaulo
1644214501Srpaulo
1645214501Srpaulostatic void wpa_send_eapol(struct wpa_authenticator *wpa_auth,
1646214501Srpaulo			   struct wpa_state_machine *sm, int key_info,
1647214501Srpaulo			   const u8 *key_rsc, const u8 *nonce,
1648214501Srpaulo			   const u8 *kde, size_t kde_len,
1649214501Srpaulo			   int keyidx, int encr)
1650214501Srpaulo{
1651214501Srpaulo	int timeout_ms;
1652214501Srpaulo	int pairwise = key_info & WPA_KEY_INFO_KEY_TYPE;
1653346981Scy	u32 ctr;
1654214501Srpaulo
1655214501Srpaulo	if (sm == NULL)
1656214501Srpaulo		return;
1657214501Srpaulo
1658214501Srpaulo	__wpa_send_eapol(wpa_auth, sm, key_info, key_rsc, nonce, kde, kde_len,
1659214501Srpaulo			 keyidx, encr, 0);
1660214501Srpaulo
1661214501Srpaulo	ctr = pairwise ? sm->TimeoutCtr : sm->GTimeoutCtr;
1662252726Srpaulo	if (ctr == 1 && wpa_auth->conf.tx_status)
1663252726Srpaulo		timeout_ms = pairwise ? eapol_key_timeout_first :
1664252726Srpaulo			eapol_key_timeout_first_group;
1665214501Srpaulo	else
1666214501Srpaulo		timeout_ms = eapol_key_timeout_subseq;
1667346981Scy	if (wpa_auth->conf.wpa_disable_eapol_key_retries &&
1668346981Scy	    (!pairwise || (key_info & WPA_KEY_INFO_MIC)))
1669346981Scy		timeout_ms = eapol_key_timeout_no_retrans;
1670252726Srpaulo	if (pairwise && ctr == 1 && !(key_info & WPA_KEY_INFO_MIC))
1671252726Srpaulo		sm->pending_1_of_4_timeout = 1;
1672346981Scy#ifdef TEST_FUZZ
1673346981Scy	timeout_ms = 1;
1674346981Scy#endif /* TEST_FUZZ */
1675252726Srpaulo	wpa_printf(MSG_DEBUG, "WPA: Use EAPOL-Key timeout of %u ms (retry "
1676346981Scy		   "counter %u)", timeout_ms, ctr);
1677214501Srpaulo	eloop_register_timeout(timeout_ms / 1000, (timeout_ms % 1000) * 1000,
1678214501Srpaulo			       wpa_send_eapol_timeout, wpa_auth, sm);
1679214501Srpaulo}
1680214501Srpaulo
1681214501Srpaulo
1682346981Scystatic int wpa_verify_key_mic(int akmp, size_t pmk_len, struct wpa_ptk *PTK,
1683346981Scy			      u8 *data, size_t data_len)
1684214501Srpaulo{
1685214501Srpaulo	struct ieee802_1x_hdr *hdr;
1686214501Srpaulo	struct wpa_eapol_key *key;
1687214501Srpaulo	u16 key_info;
1688214501Srpaulo	int ret = 0;
1689346981Scy	u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN], *mic_pos;
1690346981Scy	size_t mic_len = wpa_mic_len(akmp, pmk_len);
1691214501Srpaulo
1692214501Srpaulo	if (data_len < sizeof(*hdr) + sizeof(*key))
1693214501Srpaulo		return -1;
1694214501Srpaulo
1695214501Srpaulo	hdr = (struct ieee802_1x_hdr *) data;
1696214501Srpaulo	key = (struct wpa_eapol_key *) (hdr + 1);
1697346981Scy	mic_pos = (u8 *) (key + 1);
1698214501Srpaulo	key_info = WPA_GET_BE16(key->key_info);
1699346981Scy	os_memcpy(mic, mic_pos, mic_len);
1700346981Scy	os_memset(mic_pos, 0, mic_len);
1701281806Srpaulo	if (wpa_eapol_key_mic(PTK->kck, PTK->kck_len, akmp,
1702281806Srpaulo			      key_info & WPA_KEY_INFO_TYPE_MASK,
1703346981Scy			      data, data_len, mic_pos) ||
1704346981Scy	    os_memcmp_const(mic, mic_pos, mic_len) != 0)
1705214501Srpaulo		ret = -1;
1706346981Scy	os_memcpy(mic_pos, mic, mic_len);
1707214501Srpaulo	return ret;
1708214501Srpaulo}
1709214501Srpaulo
1710214501Srpaulo
1711214501Srpaulovoid wpa_remove_ptk(struct wpa_state_machine *sm)
1712214501Srpaulo{
1713214501Srpaulo	sm->PTK_valid = FALSE;
1714214501Srpaulo	os_memset(&sm->PTK, 0, sizeof(sm->PTK));
1715346981Scy	if (wpa_auth_set_key(sm->wpa_auth, 0, WPA_ALG_NONE, sm->addr, 0, NULL,
1716346981Scy			     0))
1717346981Scy		wpa_printf(MSG_DEBUG,
1718346981Scy			   "RSN: PTK removal from the driver failed");
1719214501Srpaulo	sm->pairwise_set = FALSE;
1720214501Srpaulo	eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm);
1721214501Srpaulo}
1722214501Srpaulo
1723214501Srpaulo
1724289549Srpauloint wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event)
1725214501Srpaulo{
1726214501Srpaulo	int remove_ptk = 1;
1727214501Srpaulo
1728214501Srpaulo	if (sm == NULL)
1729214501Srpaulo		return -1;
1730214501Srpaulo
1731214501Srpaulo	wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
1732214501Srpaulo			 "event %d notification", event);
1733214501Srpaulo
1734214501Srpaulo	switch (event) {
1735214501Srpaulo	case WPA_AUTH:
1736281806Srpaulo#ifdef CONFIG_MESH
1737281806Srpaulo		/* PTKs are derived through AMPE */
1738281806Srpaulo		if (wpa_auth_start_ampe(sm->wpa_auth, sm->addr)) {
1739281806Srpaulo			/* not mesh */
1740281806Srpaulo			break;
1741281806Srpaulo		}
1742281806Srpaulo		return 0;
1743281806Srpaulo#endif /* CONFIG_MESH */
1744214501Srpaulo	case WPA_ASSOC:
1745214501Srpaulo		break;
1746214501Srpaulo	case WPA_DEAUTH:
1747214501Srpaulo	case WPA_DISASSOC:
1748214501Srpaulo		sm->DeauthenticationRequest = TRUE;
1749346981Scy#ifdef CONFIG_IEEE80211R_AP
1750346981Scy		os_memset(sm->PMK, 0, sizeof(sm->PMK));
1751346981Scy		sm->pmk_len = 0;
1752346981Scy		os_memset(sm->xxkey, 0, sizeof(sm->xxkey));
1753346981Scy		sm->xxkey_len = 0;
1754346981Scy		os_memset(sm->pmk_r1, 0, sizeof(sm->pmk_r1));
1755346981Scy		sm->pmk_r1_len = 0;
1756346981Scy#endif /* CONFIG_IEEE80211R_AP */
1757214501Srpaulo		break;
1758214501Srpaulo	case WPA_REAUTH:
1759214501Srpaulo	case WPA_REAUTH_EAPOL:
1760214501Srpaulo		if (!sm->started) {
1761214501Srpaulo			/*
1762214501Srpaulo			 * When using WPS, we may end up here if the STA
1763214501Srpaulo			 * manages to re-associate without the previous STA
1764214501Srpaulo			 * entry getting removed. Consequently, we need to make
1765214501Srpaulo			 * sure that the WPA state machines gets initialized
1766214501Srpaulo			 * properly at this point.
1767214501Srpaulo			 */
1768214501Srpaulo			wpa_printf(MSG_DEBUG, "WPA state machine had not been "
1769214501Srpaulo				   "started - initialize now");
1770214501Srpaulo			sm->started = 1;
1771214501Srpaulo			sm->Init = TRUE;
1772214501Srpaulo			if (wpa_sm_step(sm) == 1)
1773214501Srpaulo				return 1; /* should not really happen */
1774214501Srpaulo			sm->Init = FALSE;
1775214501Srpaulo			sm->AuthenticationRequest = TRUE;
1776214501Srpaulo			break;
1777214501Srpaulo		}
1778214501Srpaulo		if (sm->GUpdateStationKeys) {
1779214501Srpaulo			/*
1780214501Srpaulo			 * Reauthentication cancels the pending group key
1781214501Srpaulo			 * update for this STA.
1782214501Srpaulo			 */
1783214501Srpaulo			sm->group->GKeyDoneStations--;
1784214501Srpaulo			sm->GUpdateStationKeys = FALSE;
1785214501Srpaulo			sm->PtkGroupInit = TRUE;
1786214501Srpaulo		}
1787214501Srpaulo		sm->ReAuthenticationRequest = TRUE;
1788214501Srpaulo		break;
1789214501Srpaulo	case WPA_ASSOC_FT:
1790346981Scy#ifdef CONFIG_IEEE80211R_AP
1791214501Srpaulo		wpa_printf(MSG_DEBUG, "FT: Retry PTK configuration "
1792214501Srpaulo			   "after association");
1793214501Srpaulo		wpa_ft_install_ptk(sm);
1794214501Srpaulo
1795214501Srpaulo		/* Using FT protocol, not WPA auth state machine */
1796214501Srpaulo		sm->ft_completed = 1;
1797346981Scy		wpa_auth_set_ptk_rekey_timer(sm);
1798214501Srpaulo		return 0;
1799346981Scy#else /* CONFIG_IEEE80211R_AP */
1800214501Srpaulo		break;
1801346981Scy#endif /* CONFIG_IEEE80211R_AP */
1802346981Scy	case WPA_ASSOC_FILS:
1803346981Scy#ifdef CONFIG_FILS
1804346981Scy		wpa_printf(MSG_DEBUG,
1805346981Scy			   "FILS: TK configuration after association");
1806346981Scy		fils_set_tk(sm);
1807346981Scy		sm->fils_completed = 1;
1808346981Scy		return 0;
1809346981Scy#else /* CONFIG_FILS */
1810346981Scy		break;
1811346981Scy#endif /* CONFIG_FILS */
1812337817Scy	case WPA_DRV_STA_REMOVED:
1813337817Scy		sm->tk_already_set = FALSE;
1814337817Scy		return 0;
1815214501Srpaulo	}
1816214501Srpaulo
1817346981Scy#ifdef CONFIG_IEEE80211R_AP
1818214501Srpaulo	sm->ft_completed = 0;
1819346981Scy#endif /* CONFIG_IEEE80211R_AP */
1820214501Srpaulo
1821214501Srpaulo#ifdef CONFIG_IEEE80211W
1822214501Srpaulo	if (sm->mgmt_frame_prot && event == WPA_AUTH)
1823214501Srpaulo		remove_ptk = 0;
1824214501Srpaulo#endif /* CONFIG_IEEE80211W */
1825346981Scy#ifdef CONFIG_FILS
1826346981Scy	if (wpa_key_mgmt_fils(sm->wpa_key_mgmt) &&
1827346981Scy	    (event == WPA_AUTH || event == WPA_ASSOC))
1828346981Scy		remove_ptk = 0;
1829346981Scy#endif /* CONFIG_FILS */
1830214501Srpaulo
1831214501Srpaulo	if (remove_ptk) {
1832214501Srpaulo		sm->PTK_valid = FALSE;
1833214501Srpaulo		os_memset(&sm->PTK, 0, sizeof(sm->PTK));
1834214501Srpaulo
1835214501Srpaulo		if (event != WPA_REAUTH_EAPOL)
1836214501Srpaulo			wpa_remove_ptk(sm);
1837214501Srpaulo	}
1838214501Srpaulo
1839289549Srpaulo	if (sm->in_step_loop) {
1840289549Srpaulo		/*
1841289549Srpaulo		 * wpa_sm_step() is already running - avoid recursive call to
1842289549Srpaulo		 * it by making the existing loop process the new update.
1843289549Srpaulo		 */
1844289549Srpaulo		sm->changed = TRUE;
1845289549Srpaulo		return 0;
1846289549Srpaulo	}
1847214501Srpaulo	return wpa_sm_step(sm);
1848214501Srpaulo}
1849214501Srpaulo
1850214501Srpaulo
1851214501SrpauloSM_STATE(WPA_PTK, INITIALIZE)
1852214501Srpaulo{
1853214501Srpaulo	SM_ENTRY_MA(WPA_PTK, INITIALIZE, wpa_ptk);
1854214501Srpaulo	if (sm->Init) {
1855214501Srpaulo		/* Init flag is not cleared here, so avoid busy
1856214501Srpaulo		 * loop by claiming nothing changed. */
1857214501Srpaulo		sm->changed = FALSE;
1858214501Srpaulo	}
1859214501Srpaulo
1860214501Srpaulo	sm->keycount = 0;
1861214501Srpaulo	if (sm->GUpdateStationKeys)
1862214501Srpaulo		sm->group->GKeyDoneStations--;
1863214501Srpaulo	sm->GUpdateStationKeys = FALSE;
1864214501Srpaulo	if (sm->wpa == WPA_VERSION_WPA)
1865214501Srpaulo		sm->PInitAKeys = FALSE;
1866214501Srpaulo	if (1 /* Unicast cipher supported AND (ESS OR ((IBSS or WDS) and
1867214501Srpaulo	       * Local AA > Remote AA)) */) {
1868214501Srpaulo		sm->Pair = TRUE;
1869214501Srpaulo	}
1870214501Srpaulo	wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 0);
1871214501Srpaulo	wpa_remove_ptk(sm);
1872214501Srpaulo	wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid, 0);
1873214501Srpaulo	sm->TimeoutCtr = 0;
1874346981Scy	if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
1875346981Scy	    sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP ||
1876346981Scy	    sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE) {
1877214501Srpaulo		wpa_auth_set_eapol(sm->wpa_auth, sm->addr,
1878214501Srpaulo				   WPA_EAPOL_authorized, 0);
1879214501Srpaulo	}
1880214501Srpaulo}
1881214501Srpaulo
1882214501Srpaulo
1883214501SrpauloSM_STATE(WPA_PTK, DISCONNECT)
1884214501Srpaulo{
1885346981Scy	u16 reason = sm->disconnect_reason;
1886346981Scy
1887214501Srpaulo	SM_ENTRY_MA(WPA_PTK, DISCONNECT, wpa_ptk);
1888214501Srpaulo	sm->Disconnect = FALSE;
1889346981Scy	sm->disconnect_reason = 0;
1890346981Scy	if (!reason)
1891346981Scy		reason = WLAN_REASON_PREV_AUTH_NOT_VALID;
1892346981Scy	wpa_sta_disconnect(sm->wpa_auth, sm->addr, reason);
1893214501Srpaulo}
1894214501Srpaulo
1895214501Srpaulo
1896214501SrpauloSM_STATE(WPA_PTK, DISCONNECTED)
1897214501Srpaulo{
1898214501Srpaulo	SM_ENTRY_MA(WPA_PTK, DISCONNECTED, wpa_ptk);
1899214501Srpaulo	sm->DeauthenticationRequest = FALSE;
1900214501Srpaulo}
1901214501Srpaulo
1902214501Srpaulo
1903214501SrpauloSM_STATE(WPA_PTK, AUTHENTICATION)
1904214501Srpaulo{
1905214501Srpaulo	SM_ENTRY_MA(WPA_PTK, AUTHENTICATION, wpa_ptk);
1906214501Srpaulo	os_memset(&sm->PTK, 0, sizeof(sm->PTK));
1907214501Srpaulo	sm->PTK_valid = FALSE;
1908214501Srpaulo	wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portControl_Auto,
1909214501Srpaulo			   1);
1910214501Srpaulo	wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 1);
1911214501Srpaulo	sm->AuthenticationRequest = FALSE;
1912214501Srpaulo}
1913214501Srpaulo
1914214501Srpaulo
1915252726Srpaulostatic void wpa_group_ensure_init(struct wpa_authenticator *wpa_auth,
1916252726Srpaulo				  struct wpa_group *group)
1917252726Srpaulo{
1918252726Srpaulo	if (group->first_sta_seen)
1919252726Srpaulo		return;
1920252726Srpaulo	/*
1921252726Srpaulo	 * System has run bit further than at the time hostapd was started
1922252726Srpaulo	 * potentially very early during boot up. This provides better chances
1923252726Srpaulo	 * of collecting more randomness on embedded systems. Re-initialize the
1924252726Srpaulo	 * GMK and Counter here to improve their strength if there was not
1925252726Srpaulo	 * enough entropy available immediately after system startup.
1926252726Srpaulo	 */
1927252726Srpaulo	wpa_printf(MSG_DEBUG, "WPA: Re-initialize GMK/Counter on first "
1928252726Srpaulo		   "station");
1929252726Srpaulo	if (random_pool_ready() != 1) {
1930252726Srpaulo		wpa_printf(MSG_INFO, "WPA: Not enough entropy in random pool "
1931252726Srpaulo			   "to proceed - reject first 4-way handshake");
1932252726Srpaulo		group->reject_4way_hs_for_entropy = TRUE;
1933252726Srpaulo	} else {
1934252726Srpaulo		group->first_sta_seen = TRUE;
1935252726Srpaulo		group->reject_4way_hs_for_entropy = FALSE;
1936252726Srpaulo	}
1937252726Srpaulo
1938289549Srpaulo	if (wpa_group_init_gmk_and_counter(wpa_auth, group) < 0 ||
1939289549Srpaulo	    wpa_gtk_update(wpa_auth, group) < 0 ||
1940289549Srpaulo	    wpa_group_config_group_keys(wpa_auth, group) < 0) {
1941289549Srpaulo		wpa_printf(MSG_INFO, "WPA: GMK/GTK setup failed");
1942289549Srpaulo		group->first_sta_seen = FALSE;
1943289549Srpaulo		group->reject_4way_hs_for_entropy = TRUE;
1944289549Srpaulo	}
1945252726Srpaulo}
1946252726Srpaulo
1947252726Srpaulo
1948214501SrpauloSM_STATE(WPA_PTK, AUTHENTICATION2)
1949214501Srpaulo{
1950214501Srpaulo	SM_ENTRY_MA(WPA_PTK, AUTHENTICATION2, wpa_ptk);
1951252726Srpaulo
1952252726Srpaulo	wpa_group_ensure_init(sm->wpa_auth, sm->group);
1953281806Srpaulo	sm->ReAuthenticationRequest = FALSE;
1954252726Srpaulo
1955252726Srpaulo	/*
1956252726Srpaulo	 * Definition of ANonce selection in IEEE Std 802.11i-2004 is somewhat
1957252726Srpaulo	 * ambiguous. The Authenticator state machine uses a counter that is
1958252726Srpaulo	 * incremented by one for each 4-way handshake. However, the security
1959252726Srpaulo	 * analysis of 4-way handshake points out that unpredictable nonces
1960252726Srpaulo	 * help in preventing precomputation attacks. Instead of the state
1961252726Srpaulo	 * machine definition, use an unpredictable nonce value here to provide
1962252726Srpaulo	 * stronger protection against potential precomputation attacks.
1963252726Srpaulo	 */
1964252726Srpaulo	if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) {
1965252726Srpaulo		wpa_printf(MSG_ERROR, "WPA: Failed to get random data for "
1966252726Srpaulo			   "ANonce.");
1967281806Srpaulo		sm->Disconnect = TRUE;
1968252726Srpaulo		return;
1969252726Srpaulo	}
1970252726Srpaulo	wpa_hexdump(MSG_DEBUG, "WPA: Assign ANonce", sm->ANonce,
1971252726Srpaulo		    WPA_NONCE_LEN);
1972214501Srpaulo	/* IEEE 802.11i does not clear TimeoutCtr here, but this is more
1973214501Srpaulo	 * logical place than INITIALIZE since AUTHENTICATION2 can be
1974214501Srpaulo	 * re-entered on ReAuthenticationRequest without going through
1975214501Srpaulo	 * INITIALIZE. */
1976214501Srpaulo	sm->TimeoutCtr = 0;
1977214501Srpaulo}
1978214501Srpaulo
1979214501Srpaulo
1980324697Sgordonstatic int wpa_auth_sm_ptk_update(struct wpa_state_machine *sm)
1981324697Sgordon{
1982324697Sgordon	if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) {
1983324697Sgordon		wpa_printf(MSG_ERROR,
1984324697Sgordon			   "WPA: Failed to get random data for ANonce");
1985324697Sgordon		sm->Disconnect = TRUE;
1986324697Sgordon		return -1;
1987324697Sgordon	}
1988324697Sgordon	wpa_hexdump(MSG_DEBUG, "WPA: Assign new ANonce", sm->ANonce,
1989324697Sgordon		    WPA_NONCE_LEN);
1990324697Sgordon	sm->TimeoutCtr = 0;
1991324697Sgordon	return 0;
1992324697Sgordon}
1993324697Sgordon
1994324697Sgordon
1995214501SrpauloSM_STATE(WPA_PTK, INITPMK)
1996214501Srpaulo{
1997214501Srpaulo	u8 msk[2 * PMK_LEN];
1998214501Srpaulo	size_t len = 2 * PMK_LEN;
1999214501Srpaulo
2000214501Srpaulo	SM_ENTRY_MA(WPA_PTK, INITPMK, wpa_ptk);
2001346981Scy#ifdef CONFIG_IEEE80211R_AP
2002214501Srpaulo	sm->xxkey_len = 0;
2003346981Scy#endif /* CONFIG_IEEE80211R_AP */
2004214501Srpaulo	if (sm->pmksa) {
2005214501Srpaulo		wpa_printf(MSG_DEBUG, "WPA: PMK from PMKSA cache");
2006337817Scy		os_memcpy(sm->PMK, sm->pmksa->pmk, sm->pmksa->pmk_len);
2007337817Scy		sm->pmk_len = sm->pmksa->pmk_len;
2008346981Scy#ifdef CONFIG_DPP
2009346981Scy	} else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP) {
2010346981Scy		wpa_printf(MSG_DEBUG,
2011346981Scy			   "DPP: No PMKSA cache entry for STA - reject connection");
2012346981Scy		sm->Disconnect = TRUE;
2013346981Scy		sm->disconnect_reason = WLAN_REASON_INVALID_PMKID;
2014346981Scy		return;
2015346981Scy#endif /* CONFIG_DPP */
2016214501Srpaulo	} else if (wpa_auth_get_msk(sm->wpa_auth, sm->addr, msk, &len) == 0) {
2017337817Scy		unsigned int pmk_len;
2018337817Scy
2019346981Scy		if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt))
2020337817Scy			pmk_len = PMK_LEN_SUITE_B_192;
2021337817Scy		else
2022337817Scy			pmk_len = PMK_LEN;
2023214501Srpaulo		wpa_printf(MSG_DEBUG, "WPA: PMK from EAPOL state machine "
2024337817Scy			   "(MSK len=%lu PMK len=%u)", (unsigned long) len,
2025337817Scy			   pmk_len);
2026337817Scy		if (len < pmk_len) {
2027337817Scy			wpa_printf(MSG_DEBUG,
2028337817Scy				   "WPA: MSK not long enough (%u) to create PMK (%u)",
2029337817Scy				   (unsigned int) len, (unsigned int) pmk_len);
2030337817Scy			sm->Disconnect = TRUE;
2031337817Scy			return;
2032337817Scy		}
2033337817Scy		os_memcpy(sm->PMK, msk, pmk_len);
2034337817Scy		sm->pmk_len = pmk_len;
2035346981Scy#ifdef CONFIG_IEEE80211R_AP
2036214501Srpaulo		if (len >= 2 * PMK_LEN) {
2037346981Scy			if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) {
2038346981Scy				os_memcpy(sm->xxkey, msk, SHA384_MAC_LEN);
2039346981Scy				sm->xxkey_len = SHA384_MAC_LEN;
2040346981Scy			} else {
2041346981Scy				os_memcpy(sm->xxkey, msk + PMK_LEN, PMK_LEN);
2042346981Scy				sm->xxkey_len = PMK_LEN;
2043346981Scy			}
2044214501Srpaulo		}
2045346981Scy#endif /* CONFIG_IEEE80211R_AP */
2046214501Srpaulo	} else {
2047281806Srpaulo		wpa_printf(MSG_DEBUG, "WPA: Could not get PMK, get_msk: %p",
2048346981Scy			   sm->wpa_auth->cb->get_msk);
2049281806Srpaulo		sm->Disconnect = TRUE;
2050281806Srpaulo		return;
2051214501Srpaulo	}
2052351611Scy	forced_memzero(msk, sizeof(msk));
2053214501Srpaulo
2054214501Srpaulo	sm->req_replay_counter_used = 0;
2055214501Srpaulo	/* IEEE 802.11i does not set keyRun to FALSE, but not doing this
2056214501Srpaulo	 * will break reauthentication since EAPOL state machines may not be
2057214501Srpaulo	 * get into AUTHENTICATING state that clears keyRun before WPA state
2058214501Srpaulo	 * machine enters AUTHENTICATION2 state and goes immediately to INITPMK
2059214501Srpaulo	 * state and takes PMK from the previously used AAA Key. This will
2060214501Srpaulo	 * eventually fail in 4-Way Handshake because Supplicant uses PMK
2061214501Srpaulo	 * derived from the new AAA Key. Setting keyRun = FALSE here seems to
2062214501Srpaulo	 * be good workaround for this issue. */
2063214501Srpaulo	wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyRun, 0);
2064214501Srpaulo}
2065214501Srpaulo
2066214501Srpaulo
2067214501SrpauloSM_STATE(WPA_PTK, INITPSK)
2068214501Srpaulo{
2069214501Srpaulo	const u8 *psk;
2070346981Scy	size_t psk_len;
2071346981Scy
2072214501Srpaulo	SM_ENTRY_MA(WPA_PTK, INITPSK, wpa_ptk);
2073346981Scy	psk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr, NULL,
2074346981Scy			       &psk_len, NULL);
2075214501Srpaulo	if (psk) {
2076346981Scy		os_memcpy(sm->PMK, psk, psk_len);
2077346981Scy		sm->pmk_len = psk_len;
2078346981Scy#ifdef CONFIG_IEEE80211R_AP
2079214501Srpaulo		os_memcpy(sm->xxkey, psk, PMK_LEN);
2080214501Srpaulo		sm->xxkey_len = PMK_LEN;
2081346981Scy#endif /* CONFIG_IEEE80211R_AP */
2082214501Srpaulo	}
2083346981Scy#ifdef CONFIG_SAE
2084346981Scy	if (wpa_auth_uses_sae(sm) && sm->pmksa) {
2085346981Scy		wpa_printf(MSG_DEBUG, "SAE: PMK from PMKSA cache");
2086346981Scy		os_memcpy(sm->PMK, sm->pmksa->pmk, sm->pmksa->pmk_len);
2087346981Scy		sm->pmk_len = sm->pmksa->pmk_len;
2088346981Scy#ifdef CONFIG_IEEE80211R_AP
2089346981Scy		os_memcpy(sm->xxkey, sm->pmksa->pmk, sm->pmksa->pmk_len);
2090346981Scy		sm->xxkey_len = sm->pmksa->pmk_len;
2091346981Scy#endif /* CONFIG_IEEE80211R_AP */
2092346981Scy	}
2093346981Scy#endif /* CONFIG_SAE */
2094214501Srpaulo	sm->req_replay_counter_used = 0;
2095214501Srpaulo}
2096214501Srpaulo
2097214501Srpaulo
2098214501SrpauloSM_STATE(WPA_PTK, PTKSTART)
2099214501Srpaulo{
2100214501Srpaulo	u8 buf[2 + RSN_SELECTOR_LEN + PMKID_LEN], *pmkid = NULL;
2101214501Srpaulo	size_t pmkid_len = 0;
2102214501Srpaulo
2103214501Srpaulo	SM_ENTRY_MA(WPA_PTK, PTKSTART, wpa_ptk);
2104214501Srpaulo	sm->PTKRequest = FALSE;
2105214501Srpaulo	sm->TimeoutEvt = FALSE;
2106281806Srpaulo	sm->alt_snonce_valid = FALSE;
2107214501Srpaulo
2108214501Srpaulo	sm->TimeoutCtr++;
2109346981Scy	if (sm->TimeoutCtr > sm->wpa_auth->conf.wpa_pairwise_update_count) {
2110214501Srpaulo		/* No point in sending the EAPOL-Key - we will disconnect
2111214501Srpaulo		 * immediately following this. */
2112214501Srpaulo		return;
2113214501Srpaulo	}
2114214501Srpaulo
2115214501Srpaulo	wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
2116214501Srpaulo			"sending 1/4 msg of 4-Way Handshake");
2117214501Srpaulo	/*
2118346981Scy	 * For infrastructure BSS cases, it is better for the AP not to include
2119346981Scy	 * the PMKID KDE in EAPOL-Key msg 1/4 since it could be used to initiate
2120346981Scy	 * offline search for the passphrase/PSK without having to be able to
2121346981Scy	 * capture a 4-way handshake from a STA that has access to the network.
2122346981Scy	 *
2123346981Scy	 * For IBSS cases, addition of PMKID KDE could be considered even with
2124346981Scy	 * WPA2-PSK cases that use multiple PSKs, but only if there is a single
2125346981Scy	 * possible PSK for this STA. However, this should not be done unless
2126346981Scy	 * there is support for using that information on the supplicant side.
2127346981Scy	 * The concern about exposing PMKID unnecessarily in infrastructure BSS
2128346981Scy	 * cases would also apply here, but at least in the IBSS case, this
2129346981Scy	 * would cover a potential real use case.
2130214501Srpaulo	 */
2131214501Srpaulo	if (sm->wpa == WPA_VERSION_WPA2 &&
2132346981Scy	    (wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) ||
2133346981Scy	     (sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE && sm->pmksa) ||
2134346981Scy	     wpa_key_mgmt_sae(sm->wpa_key_mgmt)) &&
2135281806Srpaulo	    sm->wpa_key_mgmt != WPA_KEY_MGMT_OSEN) {
2136214501Srpaulo		pmkid = buf;
2137214501Srpaulo		pmkid_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN;
2138214501Srpaulo		pmkid[0] = WLAN_EID_VENDOR_SPECIFIC;
2139214501Srpaulo		pmkid[1] = RSN_SELECTOR_LEN + PMKID_LEN;
2140214501Srpaulo		RSN_SELECTOR_PUT(&pmkid[2], RSN_KEY_DATA_PMKID);
2141281806Srpaulo		if (sm->pmksa) {
2142346981Scy			wpa_hexdump(MSG_DEBUG,
2143346981Scy				    "RSN: Message 1/4 PMKID from PMKSA entry",
2144346981Scy				    sm->pmksa->pmkid, PMKID_LEN);
2145214501Srpaulo			os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN],
2146214501Srpaulo				  sm->pmksa->pmkid, PMKID_LEN);
2147281806Srpaulo		} else if (wpa_key_mgmt_suite_b(sm->wpa_key_mgmt)) {
2148281806Srpaulo			/* No KCK available to derive PMKID */
2149346981Scy			wpa_printf(MSG_DEBUG,
2150346981Scy				   "RSN: No KCK available to derive PMKID for message 1/4");
2151281806Srpaulo			pmkid = NULL;
2152346981Scy#ifdef CONFIG_FILS
2153346981Scy		} else if (wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
2154346981Scy			if (sm->pmkid_set) {
2155346981Scy				wpa_hexdump(MSG_DEBUG,
2156346981Scy					    "RSN: Message 1/4 PMKID from FILS/ERP",
2157346981Scy					    sm->pmkid, PMKID_LEN);
2158346981Scy				os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN],
2159346981Scy					  sm->pmkid, PMKID_LEN);
2160346981Scy			} else {
2161346981Scy				/* No PMKID available */
2162346981Scy				wpa_printf(MSG_DEBUG,
2163346981Scy					   "RSN: No FILS/ERP PMKID available for message 1/4");
2164346981Scy				pmkid = NULL;
2165346981Scy			}
2166346981Scy#endif /* CONFIG_FILS */
2167346981Scy#ifdef CONFIG_IEEE80211R_AP
2168346981Scy		} else if (wpa_key_mgmt_ft(sm->wpa_key_mgmt) &&
2169346981Scy			   sm->ft_completed) {
2170346981Scy			wpa_printf(MSG_DEBUG,
2171346981Scy				   "FT: No PMKID in message 1/4 when using FT protocol");
2172346981Scy			pmkid = NULL;
2173346981Scy			pmkid_len = 0;
2174346981Scy#endif /* CONFIG_IEEE80211R_AP */
2175346981Scy#ifdef CONFIG_SAE
2176346981Scy		} else if (wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
2177346981Scy			if (sm->pmkid_set) {
2178346981Scy				wpa_hexdump(MSG_DEBUG,
2179346981Scy					    "RSN: Message 1/4 PMKID from SAE",
2180346981Scy					    sm->pmkid, PMKID_LEN);
2181346981Scy				os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN],
2182346981Scy					  sm->pmkid, PMKID_LEN);
2183346981Scy			} else {
2184346981Scy				/* No PMKID available */
2185346981Scy				wpa_printf(MSG_DEBUG,
2186346981Scy					   "RSN: No SAE PMKID available for message 1/4");
2187346981Scy				pmkid = NULL;
2188346981Scy			}
2189346981Scy#endif /* CONFIG_SAE */
2190281806Srpaulo		} else {
2191214501Srpaulo			/*
2192214501Srpaulo			 * Calculate PMKID since no PMKSA cache entry was
2193214501Srpaulo			 * available with pre-calculated PMKID.
2194214501Srpaulo			 */
2195337817Scy			rsn_pmkid(sm->PMK, sm->pmk_len, sm->wpa_auth->addr,
2196214501Srpaulo				  sm->addr, &pmkid[2 + RSN_SELECTOR_LEN],
2197346981Scy				  sm->wpa_key_mgmt);
2198346981Scy			wpa_hexdump(MSG_DEBUG,
2199346981Scy				    "RSN: Message 1/4 PMKID derived from PMK",
2200346981Scy				    &pmkid[2 + RSN_SELECTOR_LEN], PMKID_LEN);
2201214501Srpaulo		}
2202214501Srpaulo	}
2203214501Srpaulo	wpa_send_eapol(sm->wpa_auth, sm,
2204214501Srpaulo		       WPA_KEY_INFO_ACK | WPA_KEY_INFO_KEY_TYPE, NULL,
2205214501Srpaulo		       sm->ANonce, pmkid, pmkid_len, 0, 0);
2206214501Srpaulo}
2207214501Srpaulo
2208214501Srpaulo
2209281806Srpaulostatic int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
2210337817Scy			  const u8 *pmk, unsigned int pmk_len,
2211337817Scy			  struct wpa_ptk *ptk)
2212214501Srpaulo{
2213346981Scy	const u8 *z = NULL;
2214346981Scy	size_t z_len = 0;
2215214501Srpaulo
2216346981Scy#ifdef CONFIG_IEEE80211R_AP
2217346981Scy	if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
2218346981Scy		if (sm->ft_completed) {
2219346981Scy			u8 ptk_name[WPA_PMK_NAME_LEN];
2220346981Scy
2221346981Scy			return wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->pmk_r1_len,
2222346981Scy						 sm->SNonce, sm->ANonce,
2223346981Scy						 sm->addr, sm->wpa_auth->addr,
2224346981Scy						 sm->pmk_r1_name,
2225346981Scy						 ptk, ptk_name,
2226346981Scy						 sm->wpa_key_mgmt,
2227346981Scy						 sm->pairwise);
2228346981Scy		}
2229346981Scy		return wpa_auth_derive_ptk_ft(sm, ptk);
2230346981Scy	}
2231346981Scy#endif /* CONFIG_IEEE80211R_AP */
2232346981Scy
2233346981Scy#ifdef CONFIG_DPP2
2234346981Scy	if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP && sm->dpp_z) {
2235346981Scy		z = wpabuf_head(sm->dpp_z);
2236346981Scy		z_len = wpabuf_len(sm->dpp_z);
2237346981Scy	}
2238346981Scy#endif /* CONFIG_DPP2 */
2239346981Scy
2240337817Scy	return wpa_pmk_to_ptk(pmk, pmk_len, "Pairwise key expansion",
2241281806Srpaulo			      sm->wpa_auth->addr, sm->addr, sm->ANonce, snonce,
2242346981Scy			      ptk, sm->wpa_key_mgmt, sm->pairwise, z, z_len);
2243214501Srpaulo}
2244214501Srpaulo
2245214501Srpaulo
2246346981Scy#ifdef CONFIG_FILS
2247346981Scy
2248346981Scyint fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk,
2249346981Scy			 size_t pmk_len, const u8 *snonce, const u8 *anonce,
2250346981Scy			 const u8 *dhss, size_t dhss_len,
2251346981Scy			 struct wpabuf *g_sta, struct wpabuf *g_ap)
2252346981Scy{
2253346981Scy	u8 ick[FILS_ICK_MAX_LEN];
2254346981Scy	size_t ick_len;
2255346981Scy	int res;
2256346981Scy	u8 fils_ft[FILS_FT_MAX_LEN];
2257346981Scy	size_t fils_ft_len = 0;
2258346981Scy
2259346981Scy	res = fils_pmk_to_ptk(pmk, pmk_len, sm->addr, sm->wpa_auth->addr,
2260346981Scy			      snonce, anonce, dhss, dhss_len,
2261346981Scy			      &sm->PTK, ick, &ick_len,
2262346981Scy			      sm->wpa_key_mgmt, sm->pairwise,
2263346981Scy			      fils_ft, &fils_ft_len);
2264346981Scy	if (res < 0)
2265346981Scy		return res;
2266346981Scy	sm->PTK_valid = TRUE;
2267346981Scy	sm->tk_already_set = FALSE;
2268346981Scy
2269346981Scy#ifdef CONFIG_IEEE80211R_AP
2270346981Scy	if (fils_ft_len) {
2271346981Scy		struct wpa_authenticator *wpa_auth = sm->wpa_auth;
2272346981Scy		struct wpa_auth_config *conf = &wpa_auth->conf;
2273346981Scy		u8 pmk_r0[PMK_LEN_MAX], pmk_r0_name[WPA_PMK_NAME_LEN];
2274346981Scy		int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt);
2275346981Scy		size_t pmk_r0_len = use_sha384 ? SHA384_MAC_LEN : PMK_LEN;
2276346981Scy
2277346981Scy		if (wpa_derive_pmk_r0(fils_ft, fils_ft_len,
2278346981Scy				      conf->ssid, conf->ssid_len,
2279346981Scy				      conf->mobility_domain,
2280346981Scy				      conf->r0_key_holder,
2281346981Scy				      conf->r0_key_holder_len,
2282346981Scy				      sm->addr, pmk_r0, pmk_r0_name,
2283346981Scy				      use_sha384) < 0)
2284346981Scy			return -1;
2285346981Scy
2286346981Scy		wpa_hexdump_key(MSG_DEBUG, "FILS+FT: PMK-R0",
2287346981Scy				pmk_r0, pmk_r0_len);
2288346981Scy		wpa_hexdump(MSG_DEBUG, "FILS+FT: PMKR0Name",
2289346981Scy			    pmk_r0_name, WPA_PMK_NAME_LEN);
2290346981Scy		wpa_ft_store_pmk_fils(sm, pmk_r0, pmk_r0_name);
2291351611Scy		forced_memzero(fils_ft, sizeof(fils_ft));
2292346981Scy
2293346981Scy		res = wpa_derive_pmk_r1_name(pmk_r0_name, conf->r1_key_holder,
2294346981Scy					     sm->addr, sm->pmk_r1_name,
2295346981Scy					     use_sha384);
2296351611Scy		forced_memzero(pmk_r0, PMK_LEN_MAX);
2297346981Scy		if (res < 0)
2298346981Scy			return -1;
2299346981Scy		wpa_hexdump(MSG_DEBUG, "FILS+FT: PMKR1Name", sm->pmk_r1_name,
2300346981Scy			    WPA_PMK_NAME_LEN);
2301346981Scy		sm->pmk_r1_name_valid = 1;
2302346981Scy	}
2303346981Scy#endif /* CONFIG_IEEE80211R_AP */
2304346981Scy
2305346981Scy	res = fils_key_auth_sk(ick, ick_len, snonce, anonce,
2306346981Scy			       sm->addr, sm->wpa_auth->addr,
2307346981Scy			       g_sta ? wpabuf_head(g_sta) : NULL,
2308346981Scy			       g_sta ? wpabuf_len(g_sta) : 0,
2309346981Scy			       g_ap ? wpabuf_head(g_ap) : NULL,
2310346981Scy			       g_ap ? wpabuf_len(g_ap) : 0,
2311346981Scy			       sm->wpa_key_mgmt, sm->fils_key_auth_sta,
2312346981Scy			       sm->fils_key_auth_ap,
2313346981Scy			       &sm->fils_key_auth_len);
2314351611Scy	forced_memzero(ick, sizeof(ick));
2315346981Scy
2316346981Scy	/* Store nonces for (Re)Association Request/Response frame processing */
2317346981Scy	os_memcpy(sm->SNonce, snonce, FILS_NONCE_LEN);
2318346981Scy	os_memcpy(sm->ANonce, anonce, FILS_NONCE_LEN);
2319346981Scy
2320346981Scy	return res;
2321346981Scy}
2322346981Scy
2323346981Scy
2324346981Scystatic int wpa_aead_decrypt(struct wpa_state_machine *sm, struct wpa_ptk *ptk,
2325346981Scy			    u8 *buf, size_t buf_len, u16 *_key_data_len)
2326346981Scy{
2327346981Scy	struct ieee802_1x_hdr *hdr;
2328346981Scy	struct wpa_eapol_key *key;
2329346981Scy	u8 *pos;
2330346981Scy	u16 key_data_len;
2331346981Scy	u8 *tmp;
2332346981Scy	const u8 *aad[1];
2333346981Scy	size_t aad_len[1];
2334346981Scy
2335346981Scy	hdr = (struct ieee802_1x_hdr *) buf;
2336346981Scy	key = (struct wpa_eapol_key *) (hdr + 1);
2337346981Scy	pos = (u8 *) (key + 1);
2338346981Scy	key_data_len = WPA_GET_BE16(pos);
2339346981Scy	if (key_data_len < AES_BLOCK_SIZE ||
2340346981Scy	    key_data_len > buf_len - sizeof(*hdr) - sizeof(*key) - 2) {
2341346981Scy		wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO,
2342346981Scy				"No room for AES-SIV data in the frame");
2343346981Scy		return -1;
2344346981Scy	}
2345346981Scy	pos += 2; /* Pointing at the Encrypted Key Data field */
2346346981Scy
2347346981Scy	tmp = os_malloc(key_data_len);
2348346981Scy	if (!tmp)
2349346981Scy		return -1;
2350346981Scy
2351346981Scy	/* AES-SIV AAD from EAPOL protocol version field (inclusive) to
2352346981Scy	 * to Key Data (exclusive). */
2353346981Scy	aad[0] = buf;
2354346981Scy	aad_len[0] = pos - buf;
2355346981Scy	if (aes_siv_decrypt(ptk->kek, ptk->kek_len, pos, key_data_len,
2356346981Scy			    1, aad, aad_len, tmp) < 0) {
2357346981Scy		wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO,
2358346981Scy				"Invalid AES-SIV data in the frame");
2359346981Scy		bin_clear_free(tmp, key_data_len);
2360346981Scy		return -1;
2361346981Scy	}
2362346981Scy
2363346981Scy	/* AEAD decryption and validation completed successfully */
2364346981Scy	key_data_len -= AES_BLOCK_SIZE;
2365346981Scy	wpa_hexdump_key(MSG_DEBUG, "WPA: Decrypted Key Data",
2366346981Scy			tmp, key_data_len);
2367346981Scy
2368346981Scy	/* Replace Key Data field with the decrypted version */
2369346981Scy	os_memcpy(pos, tmp, key_data_len);
2370346981Scy	pos -= 2; /* Key Data Length field */
2371346981Scy	WPA_PUT_BE16(pos, key_data_len);
2372346981Scy	bin_clear_free(tmp, key_data_len);
2373346981Scy	if (_key_data_len)
2374346981Scy		*_key_data_len = key_data_len;
2375346981Scy	return 0;
2376346981Scy}
2377346981Scy
2378346981Scy
2379346981Scyconst u8 * wpa_fils_validate_fils_session(struct wpa_state_machine *sm,
2380346981Scy					  const u8 *ies, size_t ies_len,
2381346981Scy					  const u8 *fils_session)
2382346981Scy{
2383346981Scy	const u8 *ie, *end;
2384346981Scy	const u8 *session = NULL;
2385346981Scy
2386346981Scy	if (!wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
2387346981Scy		wpa_printf(MSG_DEBUG,
2388346981Scy			   "FILS: Not a FILS AKM - reject association");
2389346981Scy		return NULL;
2390346981Scy	}
2391346981Scy
2392346981Scy	/* Verify Session element */
2393346981Scy	ie = ies;
2394346981Scy	end = ((const u8 *) ie) + ies_len;
2395346981Scy	while (ie + 1 < end) {
2396346981Scy		if (ie + 2 + ie[1] > end)
2397346981Scy			break;
2398346981Scy		if (ie[0] == WLAN_EID_EXTENSION &&
2399346981Scy		    ie[1] >= 1 + FILS_SESSION_LEN &&
2400346981Scy		    ie[2] == WLAN_EID_EXT_FILS_SESSION) {
2401346981Scy			session = ie;
2402346981Scy			break;
2403346981Scy		}
2404346981Scy		ie += 2 + ie[1];
2405346981Scy	}
2406346981Scy
2407346981Scy	if (!session) {
2408346981Scy		wpa_printf(MSG_DEBUG,
2409346981Scy			   "FILS: %s: Could not find FILS Session element in Assoc Req - reject",
2410346981Scy			   __func__);
2411346981Scy		return NULL;
2412346981Scy	}
2413346981Scy
2414346981Scy	if (!fils_session) {
2415346981Scy		wpa_printf(MSG_DEBUG,
2416346981Scy			   "FILS: %s: Could not find FILS Session element in STA entry - reject",
2417346981Scy			   __func__);
2418346981Scy		return NULL;
2419346981Scy	}
2420346981Scy
2421346981Scy	if (os_memcmp(fils_session, session + 3, FILS_SESSION_LEN) != 0) {
2422346981Scy		wpa_printf(MSG_DEBUG, "FILS: Session mismatch");
2423346981Scy		wpa_hexdump(MSG_DEBUG, "FILS: Expected FILS Session",
2424346981Scy			    fils_session, FILS_SESSION_LEN);
2425346981Scy		wpa_hexdump(MSG_DEBUG, "FILS: Received FILS Session",
2426346981Scy			    session + 3, FILS_SESSION_LEN);
2427346981Scy		return NULL;
2428346981Scy	}
2429346981Scy	return session;
2430346981Scy}
2431346981Scy
2432346981Scy
2433346981Scyint wpa_fils_validate_key_confirm(struct wpa_state_machine *sm, const u8 *ies,
2434346981Scy				  size_t ies_len)
2435346981Scy{
2436346981Scy	struct ieee802_11_elems elems;
2437346981Scy
2438346981Scy	if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed) {
2439346981Scy		wpa_printf(MSG_DEBUG,
2440346981Scy			   "FILS: Failed to parse decrypted elements");
2441346981Scy		return -1;
2442346981Scy	}
2443346981Scy
2444346981Scy	if (!elems.fils_session) {
2445346981Scy		wpa_printf(MSG_DEBUG, "FILS: No FILS Session element");
2446346981Scy		return -1;
2447346981Scy	}
2448346981Scy
2449346981Scy	if (!elems.fils_key_confirm) {
2450346981Scy		wpa_printf(MSG_DEBUG, "FILS: No FILS Key Confirm element");
2451346981Scy		return -1;
2452346981Scy	}
2453346981Scy
2454346981Scy	if (elems.fils_key_confirm_len != sm->fils_key_auth_len) {
2455346981Scy		wpa_printf(MSG_DEBUG,
2456346981Scy			   "FILS: Unexpected Key-Auth length %d (expected %d)",
2457346981Scy			   elems.fils_key_confirm_len,
2458346981Scy			   (int) sm->fils_key_auth_len);
2459346981Scy		return -1;
2460346981Scy	}
2461346981Scy
2462346981Scy	if (os_memcmp(elems.fils_key_confirm, sm->fils_key_auth_sta,
2463346981Scy		      sm->fils_key_auth_len) != 0) {
2464346981Scy		wpa_printf(MSG_DEBUG, "FILS: Key-Auth mismatch");
2465346981Scy		wpa_hexdump(MSG_DEBUG, "FILS: Received Key-Auth",
2466346981Scy			    elems.fils_key_confirm, elems.fils_key_confirm_len);
2467346981Scy		wpa_hexdump(MSG_DEBUG, "FILS: Expected Key-Auth",
2468346981Scy			    sm->fils_key_auth_sta, sm->fils_key_auth_len);
2469346981Scy		return -1;
2470346981Scy	}
2471346981Scy
2472346981Scy	return 0;
2473346981Scy}
2474346981Scy
2475346981Scy
2476346981Scyint fils_decrypt_assoc(struct wpa_state_machine *sm, const u8 *fils_session,
2477346981Scy		       const struct ieee80211_mgmt *mgmt, size_t frame_len,
2478346981Scy		       u8 *pos, size_t left)
2479346981Scy{
2480346981Scy	u16 fc, stype;
2481346981Scy	const u8 *end, *ie_start, *ie, *session, *crypt;
2482346981Scy	const u8 *aad[5];
2483346981Scy	size_t aad_len[5];
2484346981Scy
2485346981Scy	if (!sm || !sm->PTK_valid) {
2486346981Scy		wpa_printf(MSG_DEBUG,
2487346981Scy			   "FILS: No KEK to decrypt Assocication Request frame");
2488346981Scy		return -1;
2489346981Scy	}
2490346981Scy
2491346981Scy	if (!wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
2492346981Scy		wpa_printf(MSG_DEBUG,
2493346981Scy			   "FILS: Not a FILS AKM - reject association");
2494346981Scy		return -1;
2495346981Scy	}
2496346981Scy
2497346981Scy	end = ((const u8 *) mgmt) + frame_len;
2498346981Scy	fc = le_to_host16(mgmt->frame_control);
2499346981Scy	stype = WLAN_FC_GET_STYPE(fc);
2500346981Scy	if (stype == WLAN_FC_STYPE_REASSOC_REQ)
2501346981Scy		ie_start = mgmt->u.reassoc_req.variable;
2502346981Scy	else
2503346981Scy		ie_start = mgmt->u.assoc_req.variable;
2504346981Scy	ie = ie_start;
2505346981Scy
2506346981Scy	/*
2507346981Scy	 * Find FILS Session element which is the last unencrypted element in
2508346981Scy	 * the frame.
2509346981Scy	 */
2510346981Scy	session = wpa_fils_validate_fils_session(sm, ie, end - ie,
2511346981Scy						 fils_session);
2512346981Scy	if (!session) {
2513346981Scy		wpa_printf(MSG_DEBUG, "FILS: Session validation failed");
2514346981Scy		return -1;
2515346981Scy	}
2516346981Scy
2517346981Scy	crypt = session + 2 + session[1];
2518346981Scy
2519346981Scy	if (end - crypt < AES_BLOCK_SIZE) {
2520346981Scy		wpa_printf(MSG_DEBUG,
2521346981Scy			   "FILS: Too short frame to include AES-SIV data");
2522346981Scy		return -1;
2523346981Scy	}
2524346981Scy
2525346981Scy	/* AES-SIV AAD vectors */
2526346981Scy
2527346981Scy	/* The STA's MAC address */
2528346981Scy	aad[0] = mgmt->sa;
2529346981Scy	aad_len[0] = ETH_ALEN;
2530346981Scy	/* The AP's BSSID */
2531346981Scy	aad[1] = mgmt->da;
2532346981Scy	aad_len[1] = ETH_ALEN;
2533346981Scy	/* The STA's nonce */
2534346981Scy	aad[2] = sm->SNonce;
2535346981Scy	aad_len[2] = FILS_NONCE_LEN;
2536346981Scy	/* The AP's nonce */
2537346981Scy	aad[3] = sm->ANonce;
2538346981Scy	aad_len[3] = FILS_NONCE_LEN;
2539346981Scy	/*
2540346981Scy	 * The (Re)Association Request frame from the Capability Information
2541346981Scy	 * field to the FILS Session element (both inclusive).
2542346981Scy	 */
2543346981Scy	aad[4] = (const u8 *) &mgmt->u.assoc_req.capab_info;
2544346981Scy	aad_len[4] = crypt - aad[4];
2545346981Scy
2546346981Scy	if (aes_siv_decrypt(sm->PTK.kek, sm->PTK.kek_len, crypt, end - crypt,
2547346981Scy			    5, aad, aad_len, pos + (crypt - ie_start)) < 0) {
2548346981Scy		wpa_printf(MSG_DEBUG,
2549346981Scy			   "FILS: Invalid AES-SIV data in the frame");
2550346981Scy		return -1;
2551346981Scy	}
2552346981Scy	wpa_hexdump(MSG_DEBUG, "FILS: Decrypted Association Request elements",
2553346981Scy		    pos, left - AES_BLOCK_SIZE);
2554346981Scy
2555346981Scy	if (wpa_fils_validate_key_confirm(sm, pos, left - AES_BLOCK_SIZE) < 0) {
2556346981Scy		wpa_printf(MSG_DEBUG, "FILS: Key Confirm validation failed");
2557346981Scy		return -1;
2558346981Scy	}
2559346981Scy
2560346981Scy	return left - AES_BLOCK_SIZE;
2561346981Scy}
2562346981Scy
2563346981Scy
2564346981Scyint fils_encrypt_assoc(struct wpa_state_machine *sm, u8 *buf,
2565346981Scy		       size_t current_len, size_t max_len,
2566346981Scy		       const struct wpabuf *hlp)
2567346981Scy{
2568346981Scy	u8 *end = buf + max_len;
2569346981Scy	u8 *pos = buf + current_len;
2570346981Scy	struct ieee80211_mgmt *mgmt;
2571346981Scy	struct wpabuf *plain;
2572346981Scy	const u8 *aad[5];
2573346981Scy	size_t aad_len[5];
2574346981Scy
2575346981Scy	if (!sm || !sm->PTK_valid)
2576346981Scy		return -1;
2577346981Scy
2578346981Scy	wpa_hexdump(MSG_DEBUG,
2579346981Scy		    "FILS: Association Response frame before FILS processing",
2580346981Scy		    buf, current_len);
2581346981Scy
2582346981Scy	mgmt = (struct ieee80211_mgmt *) buf;
2583346981Scy
2584346981Scy	/* AES-SIV AAD vectors */
2585346981Scy
2586346981Scy	/* The AP's BSSID */
2587346981Scy	aad[0] = mgmt->sa;
2588346981Scy	aad_len[0] = ETH_ALEN;
2589346981Scy	/* The STA's MAC address */
2590346981Scy	aad[1] = mgmt->da;
2591346981Scy	aad_len[1] = ETH_ALEN;
2592346981Scy	/* The AP's nonce */
2593346981Scy	aad[2] = sm->ANonce;
2594346981Scy	aad_len[2] = FILS_NONCE_LEN;
2595346981Scy	/* The STA's nonce */
2596346981Scy	aad[3] = sm->SNonce;
2597346981Scy	aad_len[3] = FILS_NONCE_LEN;
2598346981Scy	/*
2599346981Scy	 * The (Re)Association Response frame from the Capability Information
2600346981Scy	 * field (the same offset in both Association and Reassociation
2601346981Scy	 * Response frames) to the FILS Session element (both inclusive).
2602346981Scy	 */
2603346981Scy	aad[4] = (const u8 *) &mgmt->u.assoc_resp.capab_info;
2604346981Scy	aad_len[4] = pos - aad[4];
2605346981Scy
2606346981Scy	/* The following elements will be encrypted with AES-SIV */
2607346981Scy	plain = fils_prepare_plainbuf(sm, hlp);
2608346981Scy	if (!plain) {
2609346981Scy		wpa_printf(MSG_DEBUG, "FILS: Plain buffer prep failed");
2610346981Scy		return -1;
2611346981Scy	}
2612346981Scy
2613346981Scy	if (pos + wpabuf_len(plain) + AES_BLOCK_SIZE > end) {
2614346981Scy		wpa_printf(MSG_DEBUG,
2615346981Scy			   "FILS: Not enough room for FILS elements");
2616351611Scy		wpabuf_clear_free(plain);
2617346981Scy		return -1;
2618346981Scy	}
2619346981Scy
2620346981Scy	wpa_hexdump_buf_key(MSG_DEBUG, "FILS: Association Response plaintext",
2621346981Scy			    plain);
2622346981Scy
2623346981Scy	if (aes_siv_encrypt(sm->PTK.kek, sm->PTK.kek_len,
2624346981Scy			    wpabuf_head(plain), wpabuf_len(plain),
2625346981Scy			    5, aad, aad_len, pos) < 0) {
2626351611Scy		wpabuf_clear_free(plain);
2627346981Scy		return -1;
2628346981Scy	}
2629346981Scy
2630346981Scy	wpa_hexdump(MSG_DEBUG,
2631346981Scy		    "FILS: Encrypted Association Response elements",
2632346981Scy		    pos, AES_BLOCK_SIZE + wpabuf_len(plain));
2633346981Scy	current_len += wpabuf_len(plain) + AES_BLOCK_SIZE;
2634351611Scy	wpabuf_clear_free(plain);
2635346981Scy
2636346981Scy	sm->fils_completed = 1;
2637346981Scy
2638346981Scy	return current_len;
2639346981Scy}
2640346981Scy
2641346981Scy
2642346981Scystatic struct wpabuf * fils_prepare_plainbuf(struct wpa_state_machine *sm,
2643346981Scy					     const struct wpabuf *hlp)
2644346981Scy{
2645346981Scy	struct wpabuf *plain;
2646346981Scy	u8 *len, *tmp, *tmp2;
2647346981Scy	u8 hdr[2];
2648346981Scy	u8 *gtk, dummy_gtk[32];
2649346981Scy	size_t gtk_len;
2650346981Scy	struct wpa_group *gsm;
2651346981Scy
2652346981Scy	plain = wpabuf_alloc(1000);
2653346981Scy	if (!plain)
2654346981Scy		return NULL;
2655346981Scy
2656346981Scy	/* TODO: FILS Public Key */
2657346981Scy
2658346981Scy	/* FILS Key Confirmation */
2659346981Scy	wpabuf_put_u8(plain, WLAN_EID_EXTENSION); /* Element ID */
2660346981Scy	wpabuf_put_u8(plain, 1 + sm->fils_key_auth_len); /* Length */
2661346981Scy	/* Element ID Extension */
2662346981Scy	wpabuf_put_u8(plain, WLAN_EID_EXT_FILS_KEY_CONFIRM);
2663346981Scy	wpabuf_put_data(plain, sm->fils_key_auth_ap, sm->fils_key_auth_len);
2664346981Scy
2665346981Scy	/* FILS HLP Container */
2666346981Scy	if (hlp)
2667346981Scy		wpabuf_put_buf(plain, hlp);
2668346981Scy
2669346981Scy	/* TODO: FILS IP Address Assignment */
2670346981Scy
2671346981Scy	/* Key Delivery */
2672346981Scy	gsm = sm->group;
2673346981Scy	wpabuf_put_u8(plain, WLAN_EID_EXTENSION); /* Element ID */
2674346981Scy	len = wpabuf_put(plain, 1);
2675346981Scy	wpabuf_put_u8(plain, WLAN_EID_EXT_KEY_DELIVERY);
2676346981Scy	wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN,
2677346981Scy			    wpabuf_put(plain, WPA_KEY_RSC_LEN));
2678346981Scy	/* GTK KDE */
2679346981Scy	gtk = gsm->GTK[gsm->GN - 1];
2680346981Scy	gtk_len = gsm->GTK_len;
2681346981Scy	if (sm->wpa_auth->conf.disable_gtk ||
2682346981Scy	    sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
2683346981Scy		/*
2684346981Scy		 * Provide unique random GTK to each STA to prevent use
2685346981Scy		 * of GTK in the BSS.
2686346981Scy		 */
2687346981Scy		if (random_get_bytes(dummy_gtk, gtk_len) < 0) {
2688351611Scy			wpabuf_clear_free(plain);
2689346981Scy			return NULL;
2690346981Scy		}
2691346981Scy		gtk = dummy_gtk;
2692346981Scy	}
2693346981Scy	hdr[0] = gsm->GN & 0x03;
2694346981Scy	hdr[1] = 0;
2695346981Scy	tmp = wpabuf_put(plain, 0);
2696346981Scy	tmp2 = wpa_add_kde(tmp, RSN_KEY_DATA_GROUPKEY, hdr, 2,
2697346981Scy			   gtk, gtk_len);
2698346981Scy	wpabuf_put(plain, tmp2 - tmp);
2699346981Scy
2700346981Scy	/* IGTK KDE */
2701346981Scy	tmp = wpabuf_put(plain, 0);
2702346981Scy	tmp2 = ieee80211w_kde_add(sm, tmp);
2703346981Scy	wpabuf_put(plain, tmp2 - tmp);
2704346981Scy
2705346981Scy	*len = (u8 *) wpabuf_put(plain, 0) - len - 1;
2706346981Scy
2707346981Scy#ifdef CONFIG_OCV
2708346981Scy	if (wpa_auth_uses_ocv(sm)) {
2709346981Scy		struct wpa_channel_info ci;
2710346981Scy		u8 *pos;
2711346981Scy
2712346981Scy		if (wpa_channel_info(sm->wpa_auth, &ci) != 0) {
2713346981Scy			wpa_printf(MSG_WARNING,
2714346981Scy				   "FILS: Failed to get channel info for OCI element");
2715351611Scy			wpabuf_clear_free(plain);
2716346981Scy			return NULL;
2717346981Scy		}
2718346981Scy
2719346981Scy		pos = wpabuf_put(plain, OCV_OCI_EXTENDED_LEN);
2720346981Scy		if (ocv_insert_extended_oci(&ci, pos) < 0) {
2721351611Scy			wpabuf_clear_free(plain);
2722346981Scy			return NULL;
2723346981Scy		}
2724346981Scy	}
2725346981Scy#endif /* CONFIG_OCV */
2726346981Scy
2727346981Scy	return plain;
2728346981Scy}
2729346981Scy
2730346981Scy
2731346981Scyint fils_set_tk(struct wpa_state_machine *sm)
2732346981Scy{
2733346981Scy	enum wpa_alg alg;
2734346981Scy	int klen;
2735346981Scy
2736346981Scy	if (!sm || !sm->PTK_valid) {
2737346981Scy		wpa_printf(MSG_DEBUG, "FILS: No valid PTK available to set TK");
2738346981Scy		return -1;
2739346981Scy	}
2740346981Scy	if (sm->tk_already_set) {
2741346981Scy		wpa_printf(MSG_DEBUG, "FILS: TK already set to the driver");
2742346981Scy		return -1;
2743346981Scy	}
2744346981Scy
2745346981Scy	alg = wpa_cipher_to_alg(sm->pairwise);
2746346981Scy	klen = wpa_cipher_key_len(sm->pairwise);
2747346981Scy
2748346981Scy	wpa_printf(MSG_DEBUG, "FILS: Configure TK to the driver");
2749346981Scy	if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0,
2750346981Scy			     sm->PTK.tk, klen)) {
2751346981Scy		wpa_printf(MSG_DEBUG, "FILS: Failed to set TK to the driver");
2752346981Scy		return -1;
2753346981Scy	}
2754346981Scy	sm->tk_already_set = TRUE;
2755346981Scy
2756346981Scy	return 0;
2757346981Scy}
2758346981Scy
2759346981Scy
2760346981Scyu8 * hostapd_eid_assoc_fils_session(struct wpa_state_machine *sm, u8 *buf,
2761346981Scy				    const u8 *fils_session, struct wpabuf *hlp)
2762346981Scy{
2763346981Scy	struct wpabuf *plain;
2764346981Scy	u8 *pos = buf;
2765346981Scy
2766346981Scy	/* FILS Session */
2767346981Scy	*pos++ = WLAN_EID_EXTENSION; /* Element ID */
2768346981Scy	*pos++ = 1 + FILS_SESSION_LEN; /* Length */
2769346981Scy	*pos++ = WLAN_EID_EXT_FILS_SESSION; /* Element ID Extension */
2770346981Scy	os_memcpy(pos, fils_session, FILS_SESSION_LEN);
2771346981Scy	pos += FILS_SESSION_LEN;
2772346981Scy
2773346981Scy	plain = fils_prepare_plainbuf(sm, hlp);
2774346981Scy	if (!plain) {
2775346981Scy		wpa_printf(MSG_DEBUG, "FILS: Plain buffer prep failed");
2776346981Scy		return NULL;
2777346981Scy	}
2778346981Scy
2779346981Scy	os_memcpy(pos, wpabuf_head(plain), wpabuf_len(plain));
2780346981Scy	pos += wpabuf_len(plain);
2781346981Scy
2782346981Scy	wpa_printf(MSG_DEBUG, "%s: plain buf_len: %u", __func__,
2783346981Scy		   (unsigned int) wpabuf_len(plain));
2784351611Scy	wpabuf_clear_free(plain);
2785346981Scy	sm->fils_completed = 1;
2786346981Scy	return pos;
2787346981Scy}
2788346981Scy
2789346981Scy#endif /* CONFIG_FILS */
2790346981Scy
2791346981Scy
2792346981Scy#ifdef CONFIG_OCV
2793346981Scyint get_sta_tx_parameters(struct wpa_state_machine *sm, int ap_max_chanwidth,
2794346981Scy			  int ap_seg1_idx, int *bandwidth, int *seg1_idx)
2795346981Scy{
2796346981Scy	struct wpa_authenticator *wpa_auth = sm->wpa_auth;
2797346981Scy
2798346981Scy	if (!wpa_auth->cb->get_sta_tx_params)
2799346981Scy		return -1;
2800346981Scy	return wpa_auth->cb->get_sta_tx_params(wpa_auth->cb_ctx, sm->addr,
2801346981Scy					       ap_max_chanwidth, ap_seg1_idx,
2802346981Scy					       bandwidth, seg1_idx);
2803346981Scy}
2804346981Scy#endif /* CONFIG_OCV */
2805346981Scy
2806346981Scy
2807214501SrpauloSM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
2808214501Srpaulo{
2809346981Scy	struct wpa_authenticator *wpa_auth = sm->wpa_auth;
2810214501Srpaulo	struct wpa_ptk PTK;
2811289549Srpaulo	int ok = 0, psk_found = 0;
2812214501Srpaulo	const u8 *pmk = NULL;
2813346981Scy	size_t pmk_len;
2814346981Scy	int ft;
2815346981Scy	const u8 *eapol_key_ie, *key_data, *mic;
2816346981Scy	u16 key_data_length;
2817346981Scy	size_t mic_len, eapol_key_ie_len;
2818346981Scy	struct ieee802_1x_hdr *hdr;
2819346981Scy	struct wpa_eapol_key *key;
2820346981Scy	struct wpa_eapol_ie_parse kde;
2821346981Scy	int vlan_id = 0;
2822214501Srpaulo
2823214501Srpaulo	SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING, wpa_ptk);
2824214501Srpaulo	sm->EAPOLKeyReceived = FALSE;
2825252726Srpaulo	sm->update_snonce = FALSE;
2826346981Scy	os_memset(&PTK, 0, sizeof(PTK));
2827214501Srpaulo
2828346981Scy	mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
2829346981Scy
2830214501Srpaulo	/* WPA with IEEE 802.1X: use the derived PMK from EAP
2831214501Srpaulo	 * WPA-PSK: iterate through possible PSKs and select the one matching
2832214501Srpaulo	 * the packet */
2833214501Srpaulo	for (;;) {
2834346981Scy		if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
2835346981Scy		    !wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
2836281806Srpaulo			pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr,
2837346981Scy					       sm->p2p_dev_addr, pmk, &pmk_len,
2838346981Scy					       &vlan_id);
2839214501Srpaulo			if (pmk == NULL)
2840214501Srpaulo				break;
2841289549Srpaulo			psk_found = 1;
2842346981Scy#ifdef CONFIG_IEEE80211R_AP
2843346981Scy			if (wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) {
2844346981Scy				os_memcpy(sm->xxkey, pmk, pmk_len);
2845346981Scy				sm->xxkey_len = pmk_len;
2846346981Scy			}
2847346981Scy#endif /* CONFIG_IEEE80211R_AP */
2848337817Scy		} else {
2849214501Srpaulo			pmk = sm->PMK;
2850337817Scy			pmk_len = sm->pmk_len;
2851337817Scy		}
2852214501Srpaulo
2853346981Scy		if ((!pmk || !pmk_len) && sm->pmksa) {
2854346981Scy			wpa_printf(MSG_DEBUG, "WPA: Use PMK from PMKSA cache");
2855346981Scy			pmk = sm->pmksa->pmk;
2856346981Scy			pmk_len = sm->pmksa->pmk_len;
2857346981Scy		}
2858214501Srpaulo
2859346981Scy		if (wpa_derive_ptk(sm, sm->SNonce, pmk, pmk_len, &PTK) < 0)
2860346981Scy			break;
2861346981Scy
2862346981Scy		if (mic_len &&
2863346981Scy		    wpa_verify_key_mic(sm->wpa_key_mgmt, pmk_len, &PTK,
2864281806Srpaulo				       sm->last_rx_eapol_key,
2865214501Srpaulo				       sm->last_rx_eapol_key_len) == 0) {
2866346981Scy			if (sm->PMK != pmk) {
2867346981Scy				os_memcpy(sm->PMK, pmk, pmk_len);
2868346981Scy				sm->pmk_len = pmk_len;
2869346981Scy			}
2870214501Srpaulo			ok = 1;
2871214501Srpaulo			break;
2872214501Srpaulo		}
2873214501Srpaulo
2874346981Scy#ifdef CONFIG_FILS
2875346981Scy		if (!mic_len &&
2876346981Scy		    wpa_aead_decrypt(sm, &PTK, sm->last_rx_eapol_key,
2877346981Scy				     sm->last_rx_eapol_key_len, NULL) == 0) {
2878346981Scy			ok = 1;
2879214501Srpaulo			break;
2880346981Scy		}
2881346981Scy#endif /* CONFIG_FILS */
2882346981Scy
2883346981Scy		if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
2884346981Scy		    wpa_key_mgmt_sae(sm->wpa_key_mgmt))
2885346981Scy			break;
2886214501Srpaulo	}
2887214501Srpaulo
2888214501Srpaulo	if (!ok) {
2889214501Srpaulo		wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
2890214501Srpaulo				"invalid MIC in msg 2/4 of 4-Way Handshake");
2891289549Srpaulo		if (psk_found)
2892289549Srpaulo			wpa_auth_psk_failure_report(sm->wpa_auth, sm->addr);
2893214501Srpaulo		return;
2894214501Srpaulo	}
2895214501Srpaulo
2896346981Scy	/*
2897346981Scy	 * Note: last_rx_eapol_key length fields have already been validated in
2898346981Scy	 * wpa_receive().
2899346981Scy	 */
2900346981Scy	hdr = (struct ieee802_1x_hdr *) sm->last_rx_eapol_key;
2901346981Scy	key = (struct wpa_eapol_key *) (hdr + 1);
2902346981Scy	mic = (u8 *) (key + 1);
2903346981Scy	key_data = mic + mic_len + 2;
2904346981Scy	key_data_length = WPA_GET_BE16(mic + mic_len);
2905346981Scy	if (key_data_length > sm->last_rx_eapol_key_len - sizeof(*hdr) -
2906346981Scy	    sizeof(*key) - mic_len - 2)
2907346981Scy		return;
2908346981Scy
2909346981Scy	if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) {
2910346981Scy		wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
2911346981Scy				 "received EAPOL-Key msg 2/4 with invalid Key Data contents");
2912346981Scy		return;
2913346981Scy	}
2914346981Scy	if (kde.rsn_ie) {
2915346981Scy		eapol_key_ie = kde.rsn_ie;
2916346981Scy		eapol_key_ie_len = kde.rsn_ie_len;
2917346981Scy	} else if (kde.osen) {
2918346981Scy		eapol_key_ie = kde.osen;
2919346981Scy		eapol_key_ie_len = kde.osen_len;
2920346981Scy	} else {
2921346981Scy		eapol_key_ie = kde.wpa_ie;
2922346981Scy		eapol_key_ie_len = kde.wpa_ie_len;
2923346981Scy	}
2924346981Scy	ft = sm->wpa == WPA_VERSION_WPA2 && wpa_key_mgmt_ft(sm->wpa_key_mgmt);
2925346981Scy	if (sm->wpa_ie == NULL ||
2926346981Scy	    wpa_compare_rsn_ie(ft, sm->wpa_ie, sm->wpa_ie_len,
2927346981Scy			       eapol_key_ie, eapol_key_ie_len)) {
2928346981Scy		wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
2929346981Scy				"WPA IE from (Re)AssocReq did not match with msg 2/4");
2930346981Scy		if (sm->wpa_ie) {
2931346981Scy			wpa_hexdump(MSG_DEBUG, "WPA IE in AssocReq",
2932346981Scy				    sm->wpa_ie, sm->wpa_ie_len);
2933346981Scy		}
2934346981Scy		wpa_hexdump(MSG_DEBUG, "WPA IE in msg 2/4",
2935346981Scy			    eapol_key_ie, eapol_key_ie_len);
2936346981Scy		/* MLME-DEAUTHENTICATE.request */
2937346981Scy		wpa_sta_disconnect(wpa_auth, sm->addr,
2938346981Scy				   WLAN_REASON_PREV_AUTH_NOT_VALID);
2939346981Scy		return;
2940346981Scy	}
2941346981Scy#ifdef CONFIG_OCV
2942346981Scy	if (wpa_auth_uses_ocv(sm)) {
2943346981Scy		struct wpa_channel_info ci;
2944346981Scy		int tx_chanwidth;
2945346981Scy		int tx_seg1_idx;
2946346981Scy
2947346981Scy		if (wpa_channel_info(wpa_auth, &ci) != 0) {
2948346981Scy			wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
2949346981Scy					"Failed to get channel info to validate received OCI in EAPOL-Key 2/4");
2950346981Scy			return;
2951346981Scy		}
2952346981Scy
2953346981Scy		if (get_sta_tx_parameters(sm,
2954346981Scy					  channel_width_to_int(ci.chanwidth),
2955346981Scy					  ci.seg1_idx, &tx_chanwidth,
2956346981Scy					  &tx_seg1_idx) < 0)
2957346981Scy			return;
2958346981Scy
2959346981Scy		if (ocv_verify_tx_params(kde.oci, kde.oci_len, &ci,
2960346981Scy					 tx_chanwidth, tx_seg1_idx) != 0) {
2961346981Scy			wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
2962346981Scy					ocv_errorstr);
2963346981Scy			return;
2964346981Scy		}
2965346981Scy	}
2966346981Scy#endif /* CONFIG_OCV */
2967346981Scy#ifdef CONFIG_IEEE80211R_AP
2968346981Scy	if (ft && ft_check_msg_2_of_4(wpa_auth, sm, &kde) < 0) {
2969346981Scy		wpa_sta_disconnect(wpa_auth, sm->addr,
2970346981Scy				   WLAN_REASON_PREV_AUTH_NOT_VALID);
2971346981Scy		return;
2972346981Scy	}
2973346981Scy#endif /* CONFIG_IEEE80211R_AP */
2974346981Scy#ifdef CONFIG_P2P
2975346981Scy	if (kde.ip_addr_req && kde.ip_addr_req[0] &&
2976346981Scy	    wpa_auth->ip_pool && WPA_GET_BE32(sm->ip_addr) == 0) {
2977346981Scy		int idx;
2978346981Scy		wpa_printf(MSG_DEBUG,
2979346981Scy			   "P2P: IP address requested in EAPOL-Key exchange");
2980346981Scy		idx = bitfield_get_first_zero(wpa_auth->ip_pool);
2981346981Scy		if (idx >= 0) {
2982346981Scy			u32 start = WPA_GET_BE32(wpa_auth->conf.ip_addr_start);
2983346981Scy			bitfield_set(wpa_auth->ip_pool, idx);
2984346981Scy			WPA_PUT_BE32(sm->ip_addr, start + idx);
2985346981Scy			wpa_printf(MSG_DEBUG,
2986346981Scy				   "P2P: Assigned IP address %u.%u.%u.%u to "
2987346981Scy				   MACSTR, sm->ip_addr[0], sm->ip_addr[1],
2988346981Scy				   sm->ip_addr[2], sm->ip_addr[3],
2989346981Scy				   MAC2STR(sm->addr));
2990346981Scy		}
2991346981Scy	}
2992346981Scy#endif /* CONFIG_P2P */
2993346981Scy
2994346981Scy#ifdef CONFIG_IEEE80211R_AP
2995214501Srpaulo	if (sm->wpa == WPA_VERSION_WPA2 && wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
2996214501Srpaulo		/*
2997214501Srpaulo		 * Verify that PMKR1Name from EAPOL-Key message 2/4 matches
2998214501Srpaulo		 * with the value we derived.
2999214501Srpaulo		 */
3000281806Srpaulo		if (os_memcmp_const(sm->sup_pmk_r1_name, sm->pmk_r1_name,
3001281806Srpaulo				    WPA_PMK_NAME_LEN) != 0) {
3002214501Srpaulo			wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
3003214501Srpaulo					"PMKR1Name mismatch in FT 4-way "
3004214501Srpaulo					"handshake");
3005214501Srpaulo			wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from "
3006214501Srpaulo				    "Supplicant",
3007214501Srpaulo				    sm->sup_pmk_r1_name, WPA_PMK_NAME_LEN);
3008214501Srpaulo			wpa_hexdump(MSG_DEBUG, "FT: Derived PMKR1Name",
3009214501Srpaulo				    sm->pmk_r1_name, WPA_PMK_NAME_LEN);
3010214501Srpaulo			return;
3011214501Srpaulo		}
3012214501Srpaulo	}
3013346981Scy#endif /* CONFIG_IEEE80211R_AP */
3014214501Srpaulo
3015346981Scy	if (vlan_id && wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
3016346981Scy	    wpa_auth_update_vlan(wpa_auth, sm->addr, vlan_id) < 0) {
3017346981Scy		wpa_sta_disconnect(wpa_auth, sm->addr,
3018346981Scy				   WLAN_REASON_PREV_AUTH_NOT_VALID);
3019346981Scy		return;
3020346981Scy	}
3021346981Scy
3022252726Srpaulo	sm->pending_1_of_4_timeout = 0;
3023214501Srpaulo	eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm);
3024214501Srpaulo
3025214501Srpaulo	if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) {
3026214501Srpaulo		/* PSK may have changed from the previous choice, so update
3027214501Srpaulo		 * state machine data based on whatever PSK was selected here.
3028214501Srpaulo		 */
3029214501Srpaulo		os_memcpy(sm->PMK, pmk, PMK_LEN);
3030337817Scy		sm->pmk_len = PMK_LEN;
3031214501Srpaulo	}
3032214501Srpaulo
3033214501Srpaulo	sm->MICVerified = TRUE;
3034214501Srpaulo
3035214501Srpaulo	os_memcpy(&sm->PTK, &PTK, sizeof(PTK));
3036351611Scy	forced_memzero(&PTK, sizeof(PTK));
3037214501Srpaulo	sm->PTK_valid = TRUE;
3038214501Srpaulo}
3039214501Srpaulo
3040214501Srpaulo
3041214501SrpauloSM_STATE(WPA_PTK, PTKCALCNEGOTIATING2)
3042214501Srpaulo{
3043214501Srpaulo	SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING2, wpa_ptk);
3044214501Srpaulo	sm->TimeoutCtr = 0;
3045214501Srpaulo}
3046214501Srpaulo
3047214501Srpaulo
3048214501Srpaulo#ifdef CONFIG_IEEE80211W
3049214501Srpaulo
3050214501Srpaulostatic int ieee80211w_kde_len(struct wpa_state_machine *sm)
3051214501Srpaulo{
3052214501Srpaulo	if (sm->mgmt_frame_prot) {
3053281806Srpaulo		size_t len;
3054281806Srpaulo		len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
3055281806Srpaulo		return 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN + len;
3056214501Srpaulo	}
3057214501Srpaulo
3058214501Srpaulo	return 0;
3059214501Srpaulo}
3060214501Srpaulo
3061214501Srpaulo
3062214501Srpaulostatic u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos)
3063214501Srpaulo{
3064214501Srpaulo	struct wpa_igtk_kde igtk;
3065214501Srpaulo	struct wpa_group *gsm = sm->group;
3066281806Srpaulo	u8 rsc[WPA_KEY_RSC_LEN];
3067281806Srpaulo	size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
3068214501Srpaulo
3069214501Srpaulo	if (!sm->mgmt_frame_prot)
3070214501Srpaulo		return pos;
3071214501Srpaulo
3072214501Srpaulo	igtk.keyid[0] = gsm->GN_igtk;
3073214501Srpaulo	igtk.keyid[1] = 0;
3074214501Srpaulo	if (gsm->wpa_group_state != WPA_GROUP_SETKEYSDONE ||
3075281806Srpaulo	    wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, rsc) < 0)
3076214501Srpaulo		os_memset(igtk.pn, 0, sizeof(igtk.pn));
3077281806Srpaulo	else
3078281806Srpaulo		os_memcpy(igtk.pn, rsc, sizeof(igtk.pn));
3079281806Srpaulo	os_memcpy(igtk.igtk, gsm->IGTK[gsm->GN_igtk - 4], len);
3080346981Scy	if (sm->wpa_auth->conf.disable_gtk ||
3081346981Scy	    sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
3082252726Srpaulo		/*
3083252726Srpaulo		 * Provide unique random IGTK to each STA to prevent use of
3084252726Srpaulo		 * IGTK in the BSS.
3085252726Srpaulo		 */
3086281806Srpaulo		if (random_get_bytes(igtk.igtk, len) < 0)
3087252726Srpaulo			return pos;
3088252726Srpaulo	}
3089214501Srpaulo	pos = wpa_add_kde(pos, RSN_KEY_DATA_IGTK,
3090281806Srpaulo			  (const u8 *) &igtk, WPA_IGTK_KDE_PREFIX_LEN + len,
3091281806Srpaulo			  NULL, 0);
3092214501Srpaulo
3093214501Srpaulo	return pos;
3094214501Srpaulo}
3095214501Srpaulo
3096214501Srpaulo#else /* CONFIG_IEEE80211W */
3097214501Srpaulo
3098214501Srpaulostatic int ieee80211w_kde_len(struct wpa_state_machine *sm)
3099214501Srpaulo{
3100214501Srpaulo	return 0;
3101214501Srpaulo}
3102214501Srpaulo
3103214501Srpaulo
3104214501Srpaulostatic u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos)
3105214501Srpaulo{
3106214501Srpaulo	return pos;
3107214501Srpaulo}
3108214501Srpaulo
3109214501Srpaulo#endif /* CONFIG_IEEE80211W */
3110214501Srpaulo
3111214501Srpaulo
3112346981Scystatic int ocv_oci_len(struct wpa_state_machine *sm)
3113346981Scy{
3114346981Scy#ifdef CONFIG_OCV
3115346981Scy	if (wpa_auth_uses_ocv(sm))
3116346981Scy		return OCV_OCI_KDE_LEN;
3117346981Scy#endif /* CONFIG_OCV */
3118346981Scy	return 0;
3119346981Scy}
3120346981Scy
3121346981Scystatic int ocv_oci_add(struct wpa_state_machine *sm, u8 **argpos)
3122346981Scy{
3123346981Scy#ifdef CONFIG_OCV
3124346981Scy	struct wpa_channel_info ci;
3125346981Scy
3126346981Scy	if (!wpa_auth_uses_ocv(sm))
3127346981Scy		return 0;
3128346981Scy
3129346981Scy	if (wpa_channel_info(sm->wpa_auth, &ci) != 0) {
3130346981Scy		wpa_printf(MSG_WARNING,
3131346981Scy			   "Failed to get channel info for OCI element");
3132346981Scy		return -1;
3133346981Scy	}
3134346981Scy
3135346981Scy	return ocv_insert_oci_kde(&ci, argpos);
3136346981Scy#else /* CONFIG_OCV */
3137346981Scy	return 0;
3138346981Scy#endif /* CONFIG_OCV */
3139346981Scy}
3140346981Scy
3141346981Scy
3142214501SrpauloSM_STATE(WPA_PTK, PTKINITNEGOTIATING)
3143214501Srpaulo{
3144252726Srpaulo	u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde, *pos, dummy_gtk[32];
3145214501Srpaulo	size_t gtk_len, kde_len;
3146214501Srpaulo	struct wpa_group *gsm = sm->group;
3147214501Srpaulo	u8 *wpa_ie;
3148214501Srpaulo	int wpa_ie_len, secure, keyidx, encr = 0;
3149214501Srpaulo
3150214501Srpaulo	SM_ENTRY_MA(WPA_PTK, PTKINITNEGOTIATING, wpa_ptk);
3151214501Srpaulo	sm->TimeoutEvt = FALSE;
3152214501Srpaulo
3153214501Srpaulo	sm->TimeoutCtr++;
3154346981Scy	if (sm->wpa_auth->conf.wpa_disable_eapol_key_retries &&
3155346981Scy	    sm->TimeoutCtr > 1) {
3156346981Scy		/* Do not allow retransmission of EAPOL-Key msg 3/4 */
3157346981Scy		return;
3158346981Scy	}
3159346981Scy	if (sm->TimeoutCtr > sm->wpa_auth->conf.wpa_pairwise_update_count) {
3160214501Srpaulo		/* No point in sending the EAPOL-Key - we will disconnect
3161214501Srpaulo		 * immediately following this. */
3162214501Srpaulo		return;
3163214501Srpaulo	}
3164214501Srpaulo
3165214501Srpaulo	/* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, [MDIE],
3166214501Srpaulo	   GTK[GN], IGTK, [FTIE], [TIE * 2])
3167214501Srpaulo	 */
3168214501Srpaulo	os_memset(rsc, 0, WPA_KEY_RSC_LEN);
3169214501Srpaulo	wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc);
3170214501Srpaulo	/* If FT is used, wpa_auth->wpa_ie includes both RSNIE and MDIE */
3171214501Srpaulo	wpa_ie = sm->wpa_auth->wpa_ie;
3172214501Srpaulo	wpa_ie_len = sm->wpa_auth->wpa_ie_len;
3173214501Srpaulo	if (sm->wpa == WPA_VERSION_WPA &&
3174214501Srpaulo	    (sm->wpa_auth->conf.wpa & WPA_PROTO_RSN) &&
3175214501Srpaulo	    wpa_ie_len > wpa_ie[1] + 2 && wpa_ie[0] == WLAN_EID_RSN) {
3176281806Srpaulo		/* WPA-only STA, remove RSN IE and possible MDIE */
3177214501Srpaulo		wpa_ie = wpa_ie + wpa_ie[1] + 2;
3178281806Srpaulo		if (wpa_ie[0] == WLAN_EID_MOBILITY_DOMAIN)
3179281806Srpaulo			wpa_ie = wpa_ie + wpa_ie[1] + 2;
3180214501Srpaulo		wpa_ie_len = wpa_ie[1] + 2;
3181214501Srpaulo	}
3182214501Srpaulo	wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
3183214501Srpaulo			"sending 3/4 msg of 4-Way Handshake");
3184214501Srpaulo	if (sm->wpa == WPA_VERSION_WPA2) {
3185214501Srpaulo		/* WPA2 send GTK in the 4-way handshake */
3186214501Srpaulo		secure = 1;
3187214501Srpaulo		gtk = gsm->GTK[gsm->GN - 1];
3188214501Srpaulo		gtk_len = gsm->GTK_len;
3189346981Scy		if (sm->wpa_auth->conf.disable_gtk ||
3190346981Scy		    sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
3191252726Srpaulo			/*
3192252726Srpaulo			 * Provide unique random GTK to each STA to prevent use
3193252726Srpaulo			 * of GTK in the BSS.
3194252726Srpaulo			 */
3195252726Srpaulo			if (random_get_bytes(dummy_gtk, gtk_len) < 0)
3196252726Srpaulo				return;
3197252726Srpaulo			gtk = dummy_gtk;
3198252726Srpaulo		}
3199214501Srpaulo		keyidx = gsm->GN;
3200214501Srpaulo		_rsc = rsc;
3201214501Srpaulo		encr = 1;
3202214501Srpaulo	} else {
3203214501Srpaulo		/* WPA does not include GTK in msg 3/4 */
3204214501Srpaulo		secure = 0;
3205214501Srpaulo		gtk = NULL;
3206214501Srpaulo		gtk_len = 0;
3207214501Srpaulo		keyidx = 0;
3208214501Srpaulo		_rsc = NULL;
3209252726Srpaulo		if (sm->rx_eapol_key_secure) {
3210252726Srpaulo			/*
3211252726Srpaulo			 * It looks like Windows 7 supplicant tries to use
3212252726Srpaulo			 * Secure bit in msg 2/4 after having reported Michael
3213252726Srpaulo			 * MIC failure and it then rejects the 4-way handshake
3214252726Srpaulo			 * if msg 3/4 does not set Secure bit. Work around this
3215252726Srpaulo			 * by setting the Secure bit here even in the case of
3216252726Srpaulo			 * WPA if the supplicant used it first.
3217252726Srpaulo			 */
3218252726Srpaulo			wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
3219252726Srpaulo					"STA used Secure bit in WPA msg 2/4 - "
3220252726Srpaulo					"set Secure for 3/4 as workaround");
3221252726Srpaulo			secure = 1;
3222252726Srpaulo		}
3223214501Srpaulo	}
3224214501Srpaulo
3225346981Scy	kde_len = wpa_ie_len + ieee80211w_kde_len(sm) + ocv_oci_len(sm);
3226214501Srpaulo	if (gtk)
3227214501Srpaulo		kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len;
3228346981Scy#ifdef CONFIG_IEEE80211R_AP
3229214501Srpaulo	if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
3230214501Srpaulo		kde_len += 2 + PMKID_LEN; /* PMKR1Name into RSN IE */
3231214501Srpaulo		kde_len += 300; /* FTIE + 2 * TIE */
3232214501Srpaulo	}
3233346981Scy#endif /* CONFIG_IEEE80211R_AP */
3234281806Srpaulo#ifdef CONFIG_P2P
3235281806Srpaulo	if (WPA_GET_BE32(sm->ip_addr) > 0)
3236281806Srpaulo		kde_len += 2 + RSN_SELECTOR_LEN + 3 * 4;
3237281806Srpaulo#endif /* CONFIG_P2P */
3238214501Srpaulo	kde = os_malloc(kde_len);
3239214501Srpaulo	if (kde == NULL)
3240214501Srpaulo		return;
3241214501Srpaulo
3242214501Srpaulo	pos = kde;
3243214501Srpaulo	os_memcpy(pos, wpa_ie, wpa_ie_len);
3244214501Srpaulo	pos += wpa_ie_len;
3245346981Scy#ifdef CONFIG_IEEE80211R_AP
3246214501Srpaulo	if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
3247337817Scy		int res;
3248337817Scy		size_t elen;
3249337817Scy
3250337817Scy		elen = pos - kde;
3251337817Scy		res = wpa_insert_pmkid(kde, &elen, sm->pmk_r1_name);
3252214501Srpaulo		if (res < 0) {
3253214501Srpaulo			wpa_printf(MSG_ERROR, "FT: Failed to insert "
3254214501Srpaulo				   "PMKR1Name into RSN IE in EAPOL-Key data");
3255214501Srpaulo			os_free(kde);
3256214501Srpaulo			return;
3257214501Srpaulo		}
3258337817Scy		pos -= wpa_ie_len;
3259337817Scy		pos += elen;
3260214501Srpaulo	}
3261346981Scy#endif /* CONFIG_IEEE80211R_AP */
3262214501Srpaulo	if (gtk) {
3263214501Srpaulo		u8 hdr[2];
3264214501Srpaulo		hdr[0] = keyidx & 0x03;
3265214501Srpaulo		hdr[1] = 0;
3266214501Srpaulo		pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
3267214501Srpaulo				  gtk, gtk_len);
3268214501Srpaulo	}
3269214501Srpaulo	pos = ieee80211w_kde_add(sm, pos);
3270346981Scy	if (ocv_oci_add(sm, &pos) < 0) {
3271346981Scy		os_free(kde);
3272346981Scy		return;
3273346981Scy	}
3274214501Srpaulo
3275346981Scy#ifdef CONFIG_IEEE80211R_AP
3276214501Srpaulo	if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
3277214501Srpaulo		int res;
3278214501Srpaulo		struct wpa_auth_config *conf;
3279214501Srpaulo
3280214501Srpaulo		conf = &sm->wpa_auth->conf;
3281337817Scy		if (sm->assoc_resp_ftie &&
3282337817Scy		    kde + kde_len - pos >= 2 + sm->assoc_resp_ftie[1]) {
3283337817Scy			os_memcpy(pos, sm->assoc_resp_ftie,
3284337817Scy				  2 + sm->assoc_resp_ftie[1]);
3285337817Scy			res = 2 + sm->assoc_resp_ftie[1];
3286337817Scy		} else {
3287346981Scy			int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt);
3288346981Scy
3289346981Scy			res = wpa_write_ftie(conf, use_sha384,
3290346981Scy					     conf->r0_key_holder,
3291337817Scy					     conf->r0_key_holder_len,
3292337817Scy					     NULL, NULL, pos,
3293337817Scy					     kde + kde_len - pos,
3294337817Scy					     NULL, 0);
3295337817Scy		}
3296214501Srpaulo		if (res < 0) {
3297214501Srpaulo			wpa_printf(MSG_ERROR, "FT: Failed to insert FTIE "
3298214501Srpaulo				   "into EAPOL-Key Key Data");
3299214501Srpaulo			os_free(kde);
3300214501Srpaulo			return;
3301214501Srpaulo		}
3302214501Srpaulo		pos += res;
3303214501Srpaulo
3304214501Srpaulo		/* TIE[ReassociationDeadline] (TU) */
3305214501Srpaulo		*pos++ = WLAN_EID_TIMEOUT_INTERVAL;
3306214501Srpaulo		*pos++ = 5;
3307214501Srpaulo		*pos++ = WLAN_TIMEOUT_REASSOC_DEADLINE;
3308214501Srpaulo		WPA_PUT_LE32(pos, conf->reassociation_deadline);
3309214501Srpaulo		pos += 4;
3310214501Srpaulo
3311214501Srpaulo		/* TIE[KeyLifetime] (seconds) */
3312214501Srpaulo		*pos++ = WLAN_EID_TIMEOUT_INTERVAL;
3313214501Srpaulo		*pos++ = 5;
3314214501Srpaulo		*pos++ = WLAN_TIMEOUT_KEY_LIFETIME;
3315346981Scy		WPA_PUT_LE32(pos, conf->r0_key_lifetime);
3316214501Srpaulo		pos += 4;
3317214501Srpaulo	}
3318346981Scy#endif /* CONFIG_IEEE80211R_AP */
3319281806Srpaulo#ifdef CONFIG_P2P
3320281806Srpaulo	if (WPA_GET_BE32(sm->ip_addr) > 0) {
3321281806Srpaulo		u8 addr[3 * 4];
3322281806Srpaulo		os_memcpy(addr, sm->ip_addr, 4);
3323281806Srpaulo		os_memcpy(addr + 4, sm->wpa_auth->conf.ip_addr_mask, 4);
3324281806Srpaulo		os_memcpy(addr + 8, sm->wpa_auth->conf.ip_addr_go, 4);
3325281806Srpaulo		pos = wpa_add_kde(pos, WFA_KEY_DATA_IP_ADDR_ALLOC,
3326281806Srpaulo				  addr, sizeof(addr), NULL, 0);
3327281806Srpaulo	}
3328281806Srpaulo#endif /* CONFIG_P2P */
3329214501Srpaulo
3330214501Srpaulo	wpa_send_eapol(sm->wpa_auth, sm,
3331346981Scy		       (secure ? WPA_KEY_INFO_SECURE : 0) |
3332346981Scy		       (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
3333346981Scy			WPA_KEY_INFO_MIC : 0) |
3334214501Srpaulo		       WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL |
3335214501Srpaulo		       WPA_KEY_INFO_KEY_TYPE,
3336214501Srpaulo		       _rsc, sm->ANonce, kde, pos - kde, keyidx, encr);
3337214501Srpaulo	os_free(kde);
3338214501Srpaulo}
3339214501Srpaulo
3340214501Srpaulo
3341214501SrpauloSM_STATE(WPA_PTK, PTKINITDONE)
3342214501Srpaulo{
3343214501Srpaulo	SM_ENTRY_MA(WPA_PTK, PTKINITDONE, wpa_ptk);
3344214501Srpaulo	sm->EAPOLKeyReceived = FALSE;
3345214501Srpaulo	if (sm->Pair) {
3346252726Srpaulo		enum wpa_alg alg = wpa_cipher_to_alg(sm->pairwise);
3347252726Srpaulo		int klen = wpa_cipher_key_len(sm->pairwise);
3348214501Srpaulo		if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0,
3349281806Srpaulo				     sm->PTK.tk, klen)) {
3350346981Scy			wpa_sta_disconnect(sm->wpa_auth, sm->addr,
3351346981Scy					   WLAN_REASON_PREV_AUTH_NOT_VALID);
3352214501Srpaulo			return;
3353214501Srpaulo		}
3354214501Srpaulo		/* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */
3355214501Srpaulo		sm->pairwise_set = TRUE;
3356214501Srpaulo
3357346981Scy		wpa_auth_set_ptk_rekey_timer(sm);
3358214501Srpaulo
3359346981Scy		if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
3360346981Scy		    sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP ||
3361346981Scy		    sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE) {
3362214501Srpaulo			wpa_auth_set_eapol(sm->wpa_auth, sm->addr,
3363214501Srpaulo					   WPA_EAPOL_authorized, 1);
3364214501Srpaulo		}
3365214501Srpaulo	}
3366214501Srpaulo
3367214501Srpaulo	if (0 /* IBSS == TRUE */) {
3368214501Srpaulo		sm->keycount++;
3369214501Srpaulo		if (sm->keycount == 2) {
3370214501Srpaulo			wpa_auth_set_eapol(sm->wpa_auth, sm->addr,
3371214501Srpaulo					   WPA_EAPOL_portValid, 1);
3372214501Srpaulo		}
3373214501Srpaulo	} else {
3374214501Srpaulo		wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid,
3375214501Srpaulo				   1);
3376214501Srpaulo	}
3377214501Srpaulo	wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyAvailable, 0);
3378214501Srpaulo	wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyDone, 1);
3379214501Srpaulo	if (sm->wpa == WPA_VERSION_WPA)
3380214501Srpaulo		sm->PInitAKeys = TRUE;
3381214501Srpaulo	else
3382214501Srpaulo		sm->has_GTK = TRUE;
3383214501Srpaulo	wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO,
3384214501Srpaulo			 "pairwise key handshake completed (%s)",
3385214501Srpaulo			 sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN");
3386214501Srpaulo
3387346981Scy#ifdef CONFIG_IEEE80211R_AP
3388214501Srpaulo	wpa_ft_push_pmk_r1(sm->wpa_auth, sm->addr);
3389346981Scy#endif /* CONFIG_IEEE80211R_AP */
3390214501Srpaulo}
3391214501Srpaulo
3392214501Srpaulo
3393214501SrpauloSM_STEP(WPA_PTK)
3394214501Srpaulo{
3395214501Srpaulo	struct wpa_authenticator *wpa_auth = sm->wpa_auth;
3396214501Srpaulo
3397214501Srpaulo	if (sm->Init)
3398214501Srpaulo		SM_ENTER(WPA_PTK, INITIALIZE);
3399214501Srpaulo	else if (sm->Disconnect
3400252726Srpaulo		 /* || FIX: dot11RSNAConfigSALifetime timeout */) {
3401252726Srpaulo		wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
3402252726Srpaulo				"WPA_PTK: sm->Disconnect");
3403214501Srpaulo		SM_ENTER(WPA_PTK, DISCONNECT);
3404252726Srpaulo	}
3405214501Srpaulo	else if (sm->DeauthenticationRequest)
3406214501Srpaulo		SM_ENTER(WPA_PTK, DISCONNECTED);
3407214501Srpaulo	else if (sm->AuthenticationRequest)
3408214501Srpaulo		SM_ENTER(WPA_PTK, AUTHENTICATION);
3409214501Srpaulo	else if (sm->ReAuthenticationRequest)
3410214501Srpaulo		SM_ENTER(WPA_PTK, AUTHENTICATION2);
3411324697Sgordon	else if (sm->PTKRequest) {
3412324697Sgordon		if (wpa_auth_sm_ptk_update(sm) < 0)
3413324697Sgordon			SM_ENTER(WPA_PTK, DISCONNECTED);
3414324697Sgordon		else
3415324697Sgordon			SM_ENTER(WPA_PTK, PTKSTART);
3416324697Sgordon	} else switch (sm->wpa_ptk_state) {
3417214501Srpaulo	case WPA_PTK_INITIALIZE:
3418214501Srpaulo		break;
3419214501Srpaulo	case WPA_PTK_DISCONNECT:
3420214501Srpaulo		SM_ENTER(WPA_PTK, DISCONNECTED);
3421214501Srpaulo		break;
3422214501Srpaulo	case WPA_PTK_DISCONNECTED:
3423214501Srpaulo		SM_ENTER(WPA_PTK, INITIALIZE);
3424214501Srpaulo		break;
3425214501Srpaulo	case WPA_PTK_AUTHENTICATION:
3426214501Srpaulo		SM_ENTER(WPA_PTK, AUTHENTICATION2);
3427214501Srpaulo		break;
3428214501Srpaulo	case WPA_PTK_AUTHENTICATION2:
3429214501Srpaulo		if (wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) &&
3430214501Srpaulo		    wpa_auth_get_eapol(sm->wpa_auth, sm->addr,
3431214501Srpaulo				       WPA_EAPOL_keyRun) > 0)
3432214501Srpaulo			SM_ENTER(WPA_PTK, INITPMK);
3433346981Scy		else if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
3434346981Scy			 sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE
3435214501Srpaulo			 /* FIX: && 802.1X::keyRun */)
3436214501Srpaulo			SM_ENTER(WPA_PTK, INITPSK);
3437346981Scy		else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP)
3438346981Scy			SM_ENTER(WPA_PTK, INITPMK);
3439214501Srpaulo		break;
3440214501Srpaulo	case WPA_PTK_INITPMK:
3441214501Srpaulo		if (wpa_auth_get_eapol(sm->wpa_auth, sm->addr,
3442346981Scy				       WPA_EAPOL_keyAvailable) > 0) {
3443214501Srpaulo			SM_ENTER(WPA_PTK, PTKSTART);
3444346981Scy#ifdef CONFIG_DPP
3445346981Scy		} else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP && sm->pmksa) {
3446346981Scy			SM_ENTER(WPA_PTK, PTKSTART);
3447346981Scy#endif /* CONFIG_DPP */
3448346981Scy		} else {
3449214501Srpaulo			wpa_auth->dot11RSNA4WayHandshakeFailures++;
3450252726Srpaulo			wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO,
3451252726Srpaulo					"INITPMK - keyAvailable = false");
3452214501Srpaulo			SM_ENTER(WPA_PTK, DISCONNECT);
3453214501Srpaulo		}
3454214501Srpaulo		break;
3455214501Srpaulo	case WPA_PTK_INITPSK:
3456281806Srpaulo		if (wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr,
3457346981Scy				     NULL, NULL, NULL)) {
3458214501Srpaulo			SM_ENTER(WPA_PTK, PTKSTART);
3459346981Scy#ifdef CONFIG_SAE
3460346981Scy		} else if (wpa_auth_uses_sae(sm) && sm->pmksa) {
3461346981Scy			SM_ENTER(WPA_PTK, PTKSTART);
3462346981Scy#endif /* CONFIG_SAE */
3463346981Scy		} else {
3464214501Srpaulo			wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO,
3465214501Srpaulo					"no PSK configured for the STA");
3466214501Srpaulo			wpa_auth->dot11RSNA4WayHandshakeFailures++;
3467214501Srpaulo			SM_ENTER(WPA_PTK, DISCONNECT);
3468214501Srpaulo		}
3469214501Srpaulo		break;
3470214501Srpaulo	case WPA_PTK_PTKSTART:
3471214501Srpaulo		if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest &&
3472214501Srpaulo		    sm->EAPOLKeyPairwise)
3473214501Srpaulo			SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING);
3474214501Srpaulo		else if (sm->TimeoutCtr >
3475346981Scy			 sm->wpa_auth->conf.wpa_pairwise_update_count) {
3476214501Srpaulo			wpa_auth->dot11RSNA4WayHandshakeFailures++;
3477346981Scy			wpa_auth_vlogger(
3478346981Scy				sm->wpa_auth, sm->addr, LOGGER_DEBUG,
3479346981Scy				"PTKSTART: Retry limit %u reached",
3480346981Scy				sm->wpa_auth->conf.wpa_pairwise_update_count);
3481214501Srpaulo			SM_ENTER(WPA_PTK, DISCONNECT);
3482214501Srpaulo		} else if (sm->TimeoutEvt)
3483214501Srpaulo			SM_ENTER(WPA_PTK, PTKSTART);
3484214501Srpaulo		break;
3485214501Srpaulo	case WPA_PTK_PTKCALCNEGOTIATING:
3486214501Srpaulo		if (sm->MICVerified)
3487214501Srpaulo			SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING2);
3488214501Srpaulo		else if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest &&
3489214501Srpaulo			 sm->EAPOLKeyPairwise)
3490214501Srpaulo			SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING);
3491214501Srpaulo		else if (sm->TimeoutEvt)
3492214501Srpaulo			SM_ENTER(WPA_PTK, PTKSTART);
3493214501Srpaulo		break;
3494214501Srpaulo	case WPA_PTK_PTKCALCNEGOTIATING2:
3495214501Srpaulo		SM_ENTER(WPA_PTK, PTKINITNEGOTIATING);
3496214501Srpaulo		break;
3497214501Srpaulo	case WPA_PTK_PTKINITNEGOTIATING:
3498252726Srpaulo		if (sm->update_snonce)
3499252726Srpaulo			SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING);
3500252726Srpaulo		else if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest &&
3501252726Srpaulo			 sm->EAPOLKeyPairwise && sm->MICVerified)
3502214501Srpaulo			SM_ENTER(WPA_PTK, PTKINITDONE);
3503214501Srpaulo		else if (sm->TimeoutCtr >
3504346981Scy			 sm->wpa_auth->conf.wpa_pairwise_update_count ||
3505346981Scy			 (sm->wpa_auth->conf.wpa_disable_eapol_key_retries &&
3506346981Scy			  sm->TimeoutCtr > 1)) {
3507214501Srpaulo			wpa_auth->dot11RSNA4WayHandshakeFailures++;
3508346981Scy			wpa_auth_vlogger(
3509346981Scy				sm->wpa_auth, sm->addr, LOGGER_DEBUG,
3510346981Scy				"PTKINITNEGOTIATING: Retry limit %u reached",
3511346981Scy				sm->wpa_auth->conf.wpa_pairwise_update_count);
3512214501Srpaulo			SM_ENTER(WPA_PTK, DISCONNECT);
3513214501Srpaulo		} else if (sm->TimeoutEvt)
3514214501Srpaulo			SM_ENTER(WPA_PTK, PTKINITNEGOTIATING);
3515214501Srpaulo		break;
3516214501Srpaulo	case WPA_PTK_PTKINITDONE:
3517214501Srpaulo		break;
3518214501Srpaulo	}
3519214501Srpaulo}
3520214501Srpaulo
3521214501Srpaulo
3522214501SrpauloSM_STATE(WPA_PTK_GROUP, IDLE)
3523214501Srpaulo{
3524214501Srpaulo	SM_ENTRY_MA(WPA_PTK_GROUP, IDLE, wpa_ptk_group);
3525214501Srpaulo	if (sm->Init) {
3526214501Srpaulo		/* Init flag is not cleared here, so avoid busy
3527214501Srpaulo		 * loop by claiming nothing changed. */
3528214501Srpaulo		sm->changed = FALSE;
3529214501Srpaulo	}
3530214501Srpaulo	sm->GTimeoutCtr = 0;
3531214501Srpaulo}
3532214501Srpaulo
3533214501Srpaulo
3534214501SrpauloSM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING)
3535214501Srpaulo{
3536214501Srpaulo	u8 rsc[WPA_KEY_RSC_LEN];
3537214501Srpaulo	struct wpa_group *gsm = sm->group;
3538281806Srpaulo	const u8 *kde;
3539281806Srpaulo	u8 *kde_buf = NULL, *pos, hdr[2];
3540214501Srpaulo	size_t kde_len;
3541252726Srpaulo	u8 *gtk, dummy_gtk[32];
3542214501Srpaulo
3543214501Srpaulo	SM_ENTRY_MA(WPA_PTK_GROUP, REKEYNEGOTIATING, wpa_ptk_group);
3544214501Srpaulo
3545214501Srpaulo	sm->GTimeoutCtr++;
3546346981Scy	if (sm->wpa_auth->conf.wpa_disable_eapol_key_retries &&
3547346981Scy	    sm->GTimeoutCtr > 1) {
3548346981Scy		/* Do not allow retransmission of EAPOL-Key group msg 1/2 */
3549346981Scy		return;
3550346981Scy	}
3551346981Scy	if (sm->GTimeoutCtr > sm->wpa_auth->conf.wpa_group_update_count) {
3552214501Srpaulo		/* No point in sending the EAPOL-Key - we will disconnect
3553214501Srpaulo		 * immediately following this. */
3554214501Srpaulo		return;
3555214501Srpaulo	}
3556214501Srpaulo
3557214501Srpaulo	if (sm->wpa == WPA_VERSION_WPA)
3558214501Srpaulo		sm->PInitAKeys = FALSE;
3559214501Srpaulo	sm->TimeoutEvt = FALSE;
3560214501Srpaulo	/* Send EAPOL(1, 1, 1, !Pair, G, RSC, GNonce, MIC(PTK), GTK[GN]) */
3561214501Srpaulo	os_memset(rsc, 0, WPA_KEY_RSC_LEN);
3562214501Srpaulo	if (gsm->wpa_group_state == WPA_GROUP_SETKEYSDONE)
3563214501Srpaulo		wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc);
3564214501Srpaulo	wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
3565214501Srpaulo			"sending 1/2 msg of Group Key Handshake");
3566214501Srpaulo
3567252726Srpaulo	gtk = gsm->GTK[gsm->GN - 1];
3568346981Scy	if (sm->wpa_auth->conf.disable_gtk ||
3569346981Scy	    sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) {
3570252726Srpaulo		/*
3571252726Srpaulo		 * Provide unique random GTK to each STA to prevent use
3572252726Srpaulo		 * of GTK in the BSS.
3573252726Srpaulo		 */
3574252726Srpaulo		if (random_get_bytes(dummy_gtk, gsm->GTK_len) < 0)
3575252726Srpaulo			return;
3576252726Srpaulo		gtk = dummy_gtk;
3577252726Srpaulo	}
3578214501Srpaulo	if (sm->wpa == WPA_VERSION_WPA2) {
3579214501Srpaulo		kde_len = 2 + RSN_SELECTOR_LEN + 2 + gsm->GTK_len +
3580346981Scy			ieee80211w_kde_len(sm) + ocv_oci_len(sm);
3581281806Srpaulo		kde_buf = os_malloc(kde_len);
3582281806Srpaulo		if (kde_buf == NULL)
3583214501Srpaulo			return;
3584214501Srpaulo
3585281806Srpaulo		kde = pos = kde_buf;
3586214501Srpaulo		hdr[0] = gsm->GN & 0x03;
3587214501Srpaulo		hdr[1] = 0;
3588214501Srpaulo		pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
3589252726Srpaulo				  gtk, gsm->GTK_len);
3590214501Srpaulo		pos = ieee80211w_kde_add(sm, pos);
3591346981Scy		if (ocv_oci_add(sm, &pos) < 0) {
3592346981Scy			os_free(kde_buf);
3593346981Scy			return;
3594346981Scy		}
3595281806Srpaulo		kde_len = pos - kde;
3596214501Srpaulo	} else {
3597252726Srpaulo		kde = gtk;
3598281806Srpaulo		kde_len = gsm->GTK_len;
3599214501Srpaulo	}
3600214501Srpaulo
3601214501Srpaulo	wpa_send_eapol(sm->wpa_auth, sm,
3602346981Scy		       WPA_KEY_INFO_SECURE |
3603346981Scy		       (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
3604346981Scy			WPA_KEY_INFO_MIC : 0) |
3605214501Srpaulo		       WPA_KEY_INFO_ACK |
3606214501Srpaulo		       (!sm->Pair ? WPA_KEY_INFO_INSTALL : 0),
3607346981Scy		       rsc, NULL, kde, kde_len, gsm->GN, 1);
3608281806Srpaulo
3609281806Srpaulo	os_free(kde_buf);
3610214501Srpaulo}
3611214501Srpaulo
3612214501Srpaulo
3613214501SrpauloSM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED)
3614214501Srpaulo{
3615346981Scy#ifdef CONFIG_OCV
3616346981Scy	struct wpa_authenticator *wpa_auth = sm->wpa_auth;
3617346981Scy	const u8 *key_data, *mic;
3618346981Scy	struct ieee802_1x_hdr *hdr;
3619346981Scy	struct wpa_eapol_key *key;
3620346981Scy	struct wpa_eapol_ie_parse kde;
3621346981Scy	size_t mic_len;
3622346981Scy	u16 key_data_length;
3623346981Scy#endif /* CONFIG_OCV */
3624346981Scy
3625214501Srpaulo	SM_ENTRY_MA(WPA_PTK_GROUP, REKEYESTABLISHED, wpa_ptk_group);
3626214501Srpaulo	sm->EAPOLKeyReceived = FALSE;
3627346981Scy
3628346981Scy#ifdef CONFIG_OCV
3629346981Scy	mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
3630346981Scy
3631346981Scy	/*
3632346981Scy	 * Note: last_rx_eapol_key length fields have already been validated in
3633346981Scy	 * wpa_receive().
3634346981Scy	 */
3635346981Scy	hdr = (struct ieee802_1x_hdr *) sm->last_rx_eapol_key;
3636346981Scy	key = (struct wpa_eapol_key *) (hdr + 1);
3637346981Scy	mic = (u8 *) (key + 1);
3638346981Scy	key_data = mic + mic_len + 2;
3639346981Scy	key_data_length = WPA_GET_BE16(mic + mic_len);
3640346981Scy	if (key_data_length > sm->last_rx_eapol_key_len - sizeof(*hdr) -
3641346981Scy	    sizeof(*key) - mic_len - 2)
3642346981Scy		return;
3643346981Scy
3644346981Scy	if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) {
3645346981Scy		wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
3646346981Scy				 "received EAPOL-Key group msg 2/2 with invalid Key Data contents");
3647346981Scy		return;
3648346981Scy	}
3649346981Scy
3650346981Scy	if (wpa_auth_uses_ocv(sm)) {
3651346981Scy		struct wpa_channel_info ci;
3652346981Scy		int tx_chanwidth;
3653346981Scy		int tx_seg1_idx;
3654346981Scy
3655346981Scy		if (wpa_channel_info(wpa_auth, &ci) != 0) {
3656346981Scy			wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
3657346981Scy					"Failed to get channel info to validate received OCI in EAPOL-Key group 1/2");
3658346981Scy			return;
3659346981Scy		}
3660346981Scy
3661346981Scy		if (get_sta_tx_parameters(sm,
3662346981Scy					  channel_width_to_int(ci.chanwidth),
3663346981Scy					  ci.seg1_idx, &tx_chanwidth,
3664346981Scy					  &tx_seg1_idx) < 0)
3665346981Scy			return;
3666346981Scy
3667346981Scy		if (ocv_verify_tx_params(kde.oci, kde.oci_len, &ci,
3668346981Scy					 tx_chanwidth, tx_seg1_idx) != 0) {
3669346981Scy			wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
3670346981Scy					ocv_errorstr);
3671346981Scy			return;
3672346981Scy		}
3673346981Scy	}
3674346981Scy#endif /* CONFIG_OCV */
3675346981Scy
3676214501Srpaulo	if (sm->GUpdateStationKeys)
3677214501Srpaulo		sm->group->GKeyDoneStations--;
3678214501Srpaulo	sm->GUpdateStationKeys = FALSE;
3679214501Srpaulo	sm->GTimeoutCtr = 0;
3680214501Srpaulo	/* FIX: MLME.SetProtection.Request(TA, Tx_Rx) */
3681214501Srpaulo	wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO,
3682214501Srpaulo			 "group key handshake completed (%s)",
3683214501Srpaulo			 sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN");
3684214501Srpaulo	sm->has_GTK = TRUE;
3685214501Srpaulo}
3686214501Srpaulo
3687214501Srpaulo
3688214501SrpauloSM_STATE(WPA_PTK_GROUP, KEYERROR)
3689214501Srpaulo{
3690214501Srpaulo	SM_ENTRY_MA(WPA_PTK_GROUP, KEYERROR, wpa_ptk_group);
3691214501Srpaulo	if (sm->GUpdateStationKeys)
3692214501Srpaulo		sm->group->GKeyDoneStations--;
3693214501Srpaulo	sm->GUpdateStationKeys = FALSE;
3694214501Srpaulo	sm->Disconnect = TRUE;
3695346981Scy	wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO,
3696346981Scy			 "group key handshake failed (%s) after %u tries",
3697346981Scy			 sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN",
3698346981Scy			 sm->wpa_auth->conf.wpa_group_update_count);
3699214501Srpaulo}
3700214501Srpaulo
3701214501Srpaulo
3702214501SrpauloSM_STEP(WPA_PTK_GROUP)
3703214501Srpaulo{
3704214501Srpaulo	if (sm->Init || sm->PtkGroupInit) {
3705214501Srpaulo		SM_ENTER(WPA_PTK_GROUP, IDLE);
3706214501Srpaulo		sm->PtkGroupInit = FALSE;
3707214501Srpaulo	} else switch (sm->wpa_ptk_group_state) {
3708214501Srpaulo	case WPA_PTK_GROUP_IDLE:
3709214501Srpaulo		if (sm->GUpdateStationKeys ||
3710214501Srpaulo		    (sm->wpa == WPA_VERSION_WPA && sm->PInitAKeys))
3711214501Srpaulo			SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING);
3712214501Srpaulo		break;
3713214501Srpaulo	case WPA_PTK_GROUP_REKEYNEGOTIATING:
3714214501Srpaulo		if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest &&
3715214501Srpaulo		    !sm->EAPOLKeyPairwise && sm->MICVerified)
3716214501Srpaulo			SM_ENTER(WPA_PTK_GROUP, REKEYESTABLISHED);
3717214501Srpaulo		else if (sm->GTimeoutCtr >
3718346981Scy			 sm->wpa_auth->conf.wpa_group_update_count ||
3719346981Scy			 (sm->wpa_auth->conf.wpa_disable_eapol_key_retries &&
3720346981Scy			  sm->GTimeoutCtr > 1))
3721214501Srpaulo			SM_ENTER(WPA_PTK_GROUP, KEYERROR);
3722214501Srpaulo		else if (sm->TimeoutEvt)
3723214501Srpaulo			SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING);
3724214501Srpaulo		break;
3725214501Srpaulo	case WPA_PTK_GROUP_KEYERROR:
3726214501Srpaulo		SM_ENTER(WPA_PTK_GROUP, IDLE);
3727214501Srpaulo		break;
3728214501Srpaulo	case WPA_PTK_GROUP_REKEYESTABLISHED:
3729214501Srpaulo		SM_ENTER(WPA_PTK_GROUP, IDLE);
3730214501Srpaulo		break;
3731214501Srpaulo	}
3732214501Srpaulo}
3733214501Srpaulo
3734214501Srpaulo
3735214501Srpaulostatic int wpa_gtk_update(struct wpa_authenticator *wpa_auth,
3736214501Srpaulo			  struct wpa_group *group)
3737214501Srpaulo{
3738214501Srpaulo	int ret = 0;
3739214501Srpaulo
3740214501Srpaulo	os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
3741214501Srpaulo	inc_byte_array(group->Counter, WPA_NONCE_LEN);
3742252726Srpaulo	if (wpa_gmk_to_gtk(group->GMK, "Group key expansion",
3743252726Srpaulo			   wpa_auth->addr, group->GNonce,
3744252726Srpaulo			   group->GTK[group->GN - 1], group->GTK_len) < 0)
3745252726Srpaulo		ret = -1;
3746252726Srpaulo	wpa_hexdump_key(MSG_DEBUG, "GTK",
3747252726Srpaulo			group->GTK[group->GN - 1], group->GTK_len);
3748214501Srpaulo
3749214501Srpaulo#ifdef CONFIG_IEEE80211W
3750214501Srpaulo	if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) {
3751281806Srpaulo		size_t len;
3752281806Srpaulo		len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher);
3753252726Srpaulo		os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
3754252726Srpaulo		inc_byte_array(group->Counter, WPA_NONCE_LEN);
3755252726Srpaulo		if (wpa_gmk_to_gtk(group->GMK, "IGTK key expansion",
3756252726Srpaulo				   wpa_auth->addr, group->GNonce,
3757281806Srpaulo				   group->IGTK[group->GN_igtk - 4], len) < 0)
3758214501Srpaulo			ret = -1;
3759214501Srpaulo		wpa_hexdump_key(MSG_DEBUG, "IGTK",
3760281806Srpaulo				group->IGTK[group->GN_igtk - 4], len);
3761214501Srpaulo	}
3762214501Srpaulo#endif /* CONFIG_IEEE80211W */
3763214501Srpaulo
3764214501Srpaulo	return ret;
3765214501Srpaulo}
3766214501Srpaulo
3767214501Srpaulo
3768214501Srpaulostatic void wpa_group_gtk_init(struct wpa_authenticator *wpa_auth,
3769214501Srpaulo			       struct wpa_group *group)
3770214501Srpaulo{
3771214501Srpaulo	wpa_printf(MSG_DEBUG, "WPA: group state machine entering state "
3772214501Srpaulo		   "GTK_INIT (VLAN-ID %d)", group->vlan_id);
3773214501Srpaulo	group->changed = FALSE; /* GInit is not cleared here; avoid loop */
3774214501Srpaulo	group->wpa_group_state = WPA_GROUP_GTK_INIT;
3775214501Srpaulo
3776214501Srpaulo	/* GTK[0..N] = 0 */
3777214501Srpaulo	os_memset(group->GTK, 0, sizeof(group->GTK));
3778214501Srpaulo	group->GN = 1;
3779214501Srpaulo	group->GM = 2;
3780214501Srpaulo#ifdef CONFIG_IEEE80211W
3781214501Srpaulo	group->GN_igtk = 4;
3782214501Srpaulo	group->GM_igtk = 5;
3783214501Srpaulo#endif /* CONFIG_IEEE80211W */
3784214501Srpaulo	/* GTK[GN] = CalcGTK() */
3785214501Srpaulo	wpa_gtk_update(wpa_auth, group);
3786214501Srpaulo}
3787214501Srpaulo
3788214501Srpaulo
3789214501Srpaulostatic int wpa_group_update_sta(struct wpa_state_machine *sm, void *ctx)
3790214501Srpaulo{
3791252726Srpaulo	if (ctx != NULL && ctx != sm->group)
3792252726Srpaulo		return 0;
3793252726Srpaulo
3794214501Srpaulo	if (sm->wpa_ptk_state != WPA_PTK_PTKINITDONE) {
3795214501Srpaulo		wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
3796214501Srpaulo				"Not in PTKINITDONE; skip Group Key update");
3797252726Srpaulo		sm->GUpdateStationKeys = FALSE;
3798214501Srpaulo		return 0;
3799214501Srpaulo	}
3800214501Srpaulo	if (sm->GUpdateStationKeys) {
3801214501Srpaulo		/*
3802252726Srpaulo		 * This should not really happen, so add a debug log entry.
3803252726Srpaulo		 * Since we clear the GKeyDoneStations before the loop, the
3804252726Srpaulo		 * station needs to be counted here anyway.
3805214501Srpaulo		 */
3806214501Srpaulo		wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
3807252726Srpaulo				"GUpdateStationKeys was already set when "
3808252726Srpaulo				"marking station for GTK rekeying");
3809214501Srpaulo	}
3810252726Srpaulo
3811252726Srpaulo	/* Do not rekey GTK/IGTK when STA is in WNM-Sleep Mode */
3812252726Srpaulo	if (sm->is_wnmsleep)
3813252726Srpaulo		return 0;
3814252726Srpaulo
3815252726Srpaulo	sm->group->GKeyDoneStations++;
3816252726Srpaulo	sm->GUpdateStationKeys = TRUE;
3817252726Srpaulo
3818214501Srpaulo	wpa_sm_step(sm);
3819214501Srpaulo	return 0;
3820214501Srpaulo}
3821214501Srpaulo
3822214501Srpaulo
3823346981Scy#ifdef CONFIG_WNM_AP
3824252726Srpaulo/* update GTK when exiting WNM-Sleep Mode */
3825252726Srpaulovoid wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm)
3826252726Srpaulo{
3827281806Srpaulo	if (sm == NULL || sm->is_wnmsleep)
3828252726Srpaulo		return;
3829252726Srpaulo
3830252726Srpaulo	wpa_group_update_sta(sm, NULL);
3831252726Srpaulo}
3832252726Srpaulo
3833252726Srpaulo
3834252726Srpaulovoid wpa_set_wnmsleep(struct wpa_state_machine *sm, int flag)
3835252726Srpaulo{
3836281806Srpaulo	if (sm)
3837281806Srpaulo		sm->is_wnmsleep = !!flag;
3838252726Srpaulo}
3839252726Srpaulo
3840252726Srpaulo
3841252726Srpauloint wpa_wnmsleep_gtk_subelem(struct wpa_state_machine *sm, u8 *pos)
3842252726Srpaulo{
3843252726Srpaulo	struct wpa_group *gsm = sm->group;
3844252726Srpaulo	u8 *start = pos;
3845252726Srpaulo
3846252726Srpaulo	/*
3847252726Srpaulo	 * GTK subelement:
3848252726Srpaulo	 * Sub-elem ID[1] | Length[1] | Key Info[2] | Key Length[1] | RSC[8] |
3849252726Srpaulo	 * Key[5..32]
3850252726Srpaulo	 */
3851252726Srpaulo	*pos++ = WNM_SLEEP_SUBELEM_GTK;
3852252726Srpaulo	*pos++ = 11 + gsm->GTK_len;
3853252726Srpaulo	/* Key ID in B0-B1 of Key Info */
3854252726Srpaulo	WPA_PUT_LE16(pos, gsm->GN & 0x03);
3855252726Srpaulo	pos += 2;
3856252726Srpaulo	*pos++ = gsm->GTK_len;
3857252726Srpaulo	if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, pos) != 0)
3858252726Srpaulo		return 0;
3859252726Srpaulo	pos += 8;
3860252726Srpaulo	os_memcpy(pos, gsm->GTK[gsm->GN - 1], gsm->GTK_len);
3861252726Srpaulo	pos += gsm->GTK_len;
3862252726Srpaulo
3863252726Srpaulo	wpa_printf(MSG_DEBUG, "WNM: GTK Key ID %u in WNM-Sleep Mode exit",
3864252726Srpaulo		   gsm->GN);
3865252726Srpaulo	wpa_hexdump_key(MSG_DEBUG, "WNM: GTK in WNM-Sleep Mode exit",
3866252726Srpaulo			gsm->GTK[gsm->GN - 1], gsm->GTK_len);
3867252726Srpaulo
3868252726Srpaulo	return pos - start;
3869252726Srpaulo}
3870252726Srpaulo
3871252726Srpaulo
3872252726Srpaulo#ifdef CONFIG_IEEE80211W
3873252726Srpauloint wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos)
3874252726Srpaulo{
3875252726Srpaulo	struct wpa_group *gsm = sm->group;
3876252726Srpaulo	u8 *start = pos;
3877281806Srpaulo	size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
3878252726Srpaulo
3879252726Srpaulo	/*
3880252726Srpaulo	 * IGTK subelement:
3881252726Srpaulo	 * Sub-elem ID[1] | Length[1] | KeyID[2] | PN[6] | Key[16]
3882252726Srpaulo	 */
3883252726Srpaulo	*pos++ = WNM_SLEEP_SUBELEM_IGTK;
3884281806Srpaulo	*pos++ = 2 + 6 + len;
3885252726Srpaulo	WPA_PUT_LE16(pos, gsm->GN_igtk);
3886252726Srpaulo	pos += 2;
3887252726Srpaulo	if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, pos) != 0)
3888252726Srpaulo		return 0;
3889252726Srpaulo	pos += 6;
3890252726Srpaulo
3891281806Srpaulo	os_memcpy(pos, gsm->IGTK[gsm->GN_igtk - 4], len);
3892281806Srpaulo	pos += len;
3893252726Srpaulo
3894252726Srpaulo	wpa_printf(MSG_DEBUG, "WNM: IGTK Key ID %u in WNM-Sleep Mode exit",
3895252726Srpaulo		   gsm->GN_igtk);
3896252726Srpaulo	wpa_hexdump_key(MSG_DEBUG, "WNM: IGTK in WNM-Sleep Mode exit",
3897281806Srpaulo			gsm->IGTK[gsm->GN_igtk - 4], len);
3898252726Srpaulo
3899252726Srpaulo	return pos - start;
3900252726Srpaulo}
3901252726Srpaulo#endif /* CONFIG_IEEE80211W */
3902346981Scy#endif /* CONFIG_WNM_AP */
3903252726Srpaulo
3904252726Srpaulo
3905214501Srpaulostatic void wpa_group_setkeys(struct wpa_authenticator *wpa_auth,
3906214501Srpaulo			      struct wpa_group *group)
3907214501Srpaulo{
3908214501Srpaulo	int tmp;
3909214501Srpaulo
3910214501Srpaulo	wpa_printf(MSG_DEBUG, "WPA: group state machine entering state "
3911214501Srpaulo		   "SETKEYS (VLAN-ID %d)", group->vlan_id);
3912214501Srpaulo	group->changed = TRUE;
3913214501Srpaulo	group->wpa_group_state = WPA_GROUP_SETKEYS;
3914214501Srpaulo	group->GTKReKey = FALSE;
3915214501Srpaulo	tmp = group->GM;
3916214501Srpaulo	group->GM = group->GN;
3917214501Srpaulo	group->GN = tmp;
3918214501Srpaulo#ifdef CONFIG_IEEE80211W
3919214501Srpaulo	tmp = group->GM_igtk;
3920214501Srpaulo	group->GM_igtk = group->GN_igtk;
3921214501Srpaulo	group->GN_igtk = tmp;
3922214501Srpaulo#endif /* CONFIG_IEEE80211W */
3923214501Srpaulo	/* "GKeyDoneStations = GNoStations" is done in more robust way by
3924214501Srpaulo	 * counting the STAs that are marked with GUpdateStationKeys instead of
3925214501Srpaulo	 * including all STAs that could be in not-yet-completed state. */
3926214501Srpaulo	wpa_gtk_update(wpa_auth, group);
3927214501Srpaulo
3928252726Srpaulo	if (group->GKeyDoneStations) {
3929252726Srpaulo		wpa_printf(MSG_DEBUG, "wpa_group_setkeys: Unexpected "
3930252726Srpaulo			   "GKeyDoneStations=%d when starting new GTK rekey",
3931252726Srpaulo			   group->GKeyDoneStations);
3932252726Srpaulo		group->GKeyDoneStations = 0;
3933252726Srpaulo	}
3934252726Srpaulo	wpa_auth_for_each_sta(wpa_auth, wpa_group_update_sta, group);
3935214501Srpaulo	wpa_printf(MSG_DEBUG, "wpa_group_setkeys: GKeyDoneStations=%d",
3936214501Srpaulo		   group->GKeyDoneStations);
3937214501Srpaulo}
3938214501Srpaulo
3939214501Srpaulo
3940252726Srpaulostatic int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth,
3941252726Srpaulo				       struct wpa_group *group)
3942214501Srpaulo{
3943252726Srpaulo	int ret = 0;
3944252726Srpaulo
3945252726Srpaulo	if (wpa_auth_set_key(wpa_auth, group->vlan_id,
3946252726Srpaulo			     wpa_cipher_to_alg(wpa_auth->conf.wpa_group),
3947252726Srpaulo			     broadcast_ether_addr, group->GN,
3948252726Srpaulo			     group->GTK[group->GN - 1], group->GTK_len) < 0)
3949252726Srpaulo		ret = -1;
3950252726Srpaulo
3951252726Srpaulo#ifdef CONFIG_IEEE80211W
3952281806Srpaulo	if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) {
3953281806Srpaulo		enum wpa_alg alg;
3954281806Srpaulo		size_t len;
3955281806Srpaulo
3956281806Srpaulo		alg = wpa_cipher_to_alg(wpa_auth->conf.group_mgmt_cipher);
3957281806Srpaulo		len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher);
3958281806Srpaulo
3959281806Srpaulo		if (ret == 0 &&
3960281806Srpaulo		    wpa_auth_set_key(wpa_auth, group->vlan_id, alg,
3961281806Srpaulo				     broadcast_ether_addr, group->GN_igtk,
3962281806Srpaulo				     group->IGTK[group->GN_igtk - 4], len) < 0)
3963281806Srpaulo			ret = -1;
3964281806Srpaulo	}
3965252726Srpaulo#endif /* CONFIG_IEEE80211W */
3966252726Srpaulo
3967252726Srpaulo	return ret;
3968252726Srpaulo}
3969252726Srpaulo
3970252726Srpaulo
3971281806Srpaulostatic int wpa_group_disconnect_cb(struct wpa_state_machine *sm, void *ctx)
3972281806Srpaulo{
3973281806Srpaulo	if (sm->group == ctx) {
3974281806Srpaulo		wpa_printf(MSG_DEBUG, "WPA: Mark STA " MACSTR
3975281806Srpaulo			   " for discconnection due to fatal failure",
3976281806Srpaulo			   MAC2STR(sm->addr));
3977281806Srpaulo		sm->Disconnect = TRUE;
3978281806Srpaulo	}
3979281806Srpaulo
3980281806Srpaulo	return 0;
3981281806Srpaulo}
3982281806Srpaulo
3983281806Srpaulo
3984281806Srpaulostatic void wpa_group_fatal_failure(struct wpa_authenticator *wpa_auth,
3985281806Srpaulo				    struct wpa_group *group)
3986281806Srpaulo{
3987281806Srpaulo	wpa_printf(MSG_DEBUG, "WPA: group state machine entering state FATAL_FAILURE");
3988281806Srpaulo	group->changed = TRUE;
3989281806Srpaulo	group->wpa_group_state = WPA_GROUP_FATAL_FAILURE;
3990281806Srpaulo	wpa_auth_for_each_sta(wpa_auth, wpa_group_disconnect_cb, group);
3991281806Srpaulo}
3992281806Srpaulo
3993281806Srpaulo
3994252726Srpaulostatic int wpa_group_setkeysdone(struct wpa_authenticator *wpa_auth,
3995252726Srpaulo				 struct wpa_group *group)
3996252726Srpaulo{
3997214501Srpaulo	wpa_printf(MSG_DEBUG, "WPA: group state machine entering state "
3998214501Srpaulo		   "SETKEYSDONE (VLAN-ID %d)", group->vlan_id);
3999214501Srpaulo	group->changed = TRUE;
4000214501Srpaulo	group->wpa_group_state = WPA_GROUP_SETKEYSDONE;
4001214501Srpaulo
4002281806Srpaulo	if (wpa_group_config_group_keys(wpa_auth, group) < 0) {
4003281806Srpaulo		wpa_group_fatal_failure(wpa_auth, group);
4004252726Srpaulo		return -1;
4005281806Srpaulo	}
4006252726Srpaulo
4007252726Srpaulo	return 0;
4008214501Srpaulo}
4009214501Srpaulo
4010214501Srpaulo
4011214501Srpaulostatic void wpa_group_sm_step(struct wpa_authenticator *wpa_auth,
4012214501Srpaulo			      struct wpa_group *group)
4013214501Srpaulo{
4014214501Srpaulo	if (group->GInit) {
4015214501Srpaulo		wpa_group_gtk_init(wpa_auth, group);
4016281806Srpaulo	} else if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) {
4017281806Srpaulo		/* Do not allow group operations */
4018214501Srpaulo	} else if (group->wpa_group_state == WPA_GROUP_GTK_INIT &&
4019214501Srpaulo		   group->GTKAuthenticator) {
4020214501Srpaulo		wpa_group_setkeysdone(wpa_auth, group);
4021214501Srpaulo	} else if (group->wpa_group_state == WPA_GROUP_SETKEYSDONE &&
4022214501Srpaulo		   group->GTKReKey) {
4023214501Srpaulo		wpa_group_setkeys(wpa_auth, group);
4024214501Srpaulo	} else if (group->wpa_group_state == WPA_GROUP_SETKEYS) {
4025214501Srpaulo		if (group->GKeyDoneStations == 0)
4026214501Srpaulo			wpa_group_setkeysdone(wpa_auth, group);
4027214501Srpaulo		else if (group->GTKReKey)
4028214501Srpaulo			wpa_group_setkeys(wpa_auth, group);
4029214501Srpaulo	}
4030214501Srpaulo}
4031214501Srpaulo
4032214501Srpaulo
4033214501Srpaulostatic int wpa_sm_step(struct wpa_state_machine *sm)
4034214501Srpaulo{
4035214501Srpaulo	if (sm == NULL)
4036214501Srpaulo		return 0;
4037214501Srpaulo
4038214501Srpaulo	if (sm->in_step_loop) {
4039214501Srpaulo		/* This should not happen, but if it does, make sure we do not
4040214501Srpaulo		 * end up freeing the state machine too early by exiting the
4041214501Srpaulo		 * recursive call. */
4042214501Srpaulo		wpa_printf(MSG_ERROR, "WPA: wpa_sm_step() called recursively");
4043214501Srpaulo		return 0;
4044214501Srpaulo	}
4045214501Srpaulo
4046214501Srpaulo	sm->in_step_loop = 1;
4047214501Srpaulo	do {
4048214501Srpaulo		if (sm->pending_deinit)
4049214501Srpaulo			break;
4050214501Srpaulo
4051214501Srpaulo		sm->changed = FALSE;
4052214501Srpaulo		sm->wpa_auth->group->changed = FALSE;
4053214501Srpaulo
4054214501Srpaulo		SM_STEP_RUN(WPA_PTK);
4055214501Srpaulo		if (sm->pending_deinit)
4056214501Srpaulo			break;
4057214501Srpaulo		SM_STEP_RUN(WPA_PTK_GROUP);
4058214501Srpaulo		if (sm->pending_deinit)
4059214501Srpaulo			break;
4060214501Srpaulo		wpa_group_sm_step(sm->wpa_auth, sm->group);
4061214501Srpaulo	} while (sm->changed || sm->wpa_auth->group->changed);
4062214501Srpaulo	sm->in_step_loop = 0;
4063214501Srpaulo
4064214501Srpaulo	if (sm->pending_deinit) {
4065214501Srpaulo		wpa_printf(MSG_DEBUG, "WPA: Completing pending STA state "
4066214501Srpaulo			   "machine deinit for " MACSTR, MAC2STR(sm->addr));
4067214501Srpaulo		wpa_free_sta_sm(sm);
4068214501Srpaulo		return 1;
4069214501Srpaulo	}
4070214501Srpaulo	return 0;
4071214501Srpaulo}
4072214501Srpaulo
4073214501Srpaulo
4074214501Srpaulostatic void wpa_sm_call_step(void *eloop_ctx, void *timeout_ctx)
4075214501Srpaulo{
4076214501Srpaulo	struct wpa_state_machine *sm = eloop_ctx;
4077214501Srpaulo	wpa_sm_step(sm);
4078214501Srpaulo}
4079214501Srpaulo
4080214501Srpaulo
4081214501Srpaulovoid wpa_auth_sm_notify(struct wpa_state_machine *sm)
4082214501Srpaulo{
4083214501Srpaulo	if (sm == NULL)
4084214501Srpaulo		return;
4085214501Srpaulo	eloop_register_timeout(0, 0, wpa_sm_call_step, sm, NULL);
4086214501Srpaulo}
4087214501Srpaulo
4088214501Srpaulo
4089214501Srpaulovoid wpa_gtk_rekey(struct wpa_authenticator *wpa_auth)
4090214501Srpaulo{
4091214501Srpaulo	int tmp, i;
4092214501Srpaulo	struct wpa_group *group;
4093214501Srpaulo
4094214501Srpaulo	if (wpa_auth == NULL)
4095214501Srpaulo		return;
4096214501Srpaulo
4097214501Srpaulo	group = wpa_auth->group;
4098214501Srpaulo
4099214501Srpaulo	for (i = 0; i < 2; i++) {
4100214501Srpaulo		tmp = group->GM;
4101214501Srpaulo		group->GM = group->GN;
4102214501Srpaulo		group->GN = tmp;
4103214501Srpaulo#ifdef CONFIG_IEEE80211W
4104214501Srpaulo		tmp = group->GM_igtk;
4105214501Srpaulo		group->GM_igtk = group->GN_igtk;
4106214501Srpaulo		group->GN_igtk = tmp;
4107214501Srpaulo#endif /* CONFIG_IEEE80211W */
4108214501Srpaulo		wpa_gtk_update(wpa_auth, group);
4109252726Srpaulo		wpa_group_config_group_keys(wpa_auth, group);
4110214501Srpaulo	}
4111214501Srpaulo}
4112214501Srpaulo
4113214501Srpaulo
4114289549Srpaulostatic const char * wpa_bool_txt(int val)
4115214501Srpaulo{
4116289549Srpaulo	return val ? "TRUE" : "FALSE";
4117214501Srpaulo}
4118214501Srpaulo
4119214501Srpaulo
4120214501Srpaulo#define RSN_SUITE "%02x-%02x-%02x-%d"
4121214501Srpaulo#define RSN_SUITE_ARG(s) \
4122214501Srpaulo((s) >> 24) & 0xff, ((s) >> 16) & 0xff, ((s) >> 8) & 0xff, (s) & 0xff
4123214501Srpaulo
4124214501Srpauloint wpa_get_mib(struct wpa_authenticator *wpa_auth, char *buf, size_t buflen)
4125214501Srpaulo{
4126214501Srpaulo	int len = 0, ret;
4127214501Srpaulo	char pmkid_txt[PMKID_LEN * 2 + 1];
4128252726Srpaulo#ifdef CONFIG_RSN_PREAUTH
4129252726Srpaulo	const int preauth = 1;
4130252726Srpaulo#else /* CONFIG_RSN_PREAUTH */
4131252726Srpaulo	const int preauth = 0;
4132252726Srpaulo#endif /* CONFIG_RSN_PREAUTH */
4133214501Srpaulo
4134214501Srpaulo	if (wpa_auth == NULL)
4135214501Srpaulo		return len;
4136214501Srpaulo
4137214501Srpaulo	ret = os_snprintf(buf + len, buflen - len,
4138214501Srpaulo			  "dot11RSNAOptionImplemented=TRUE\n"
4139252726Srpaulo			  "dot11RSNAPreauthenticationImplemented=%s\n"
4140214501Srpaulo			  "dot11RSNAEnabled=%s\n"
4141214501Srpaulo			  "dot11RSNAPreauthenticationEnabled=%s\n",
4142252726Srpaulo			  wpa_bool_txt(preauth),
4143214501Srpaulo			  wpa_bool_txt(wpa_auth->conf.wpa & WPA_PROTO_RSN),
4144214501Srpaulo			  wpa_bool_txt(wpa_auth->conf.rsn_preauth));
4145281806Srpaulo	if (os_snprintf_error(buflen - len, ret))
4146214501Srpaulo		return len;
4147214501Srpaulo	len += ret;
4148214501Srpaulo
4149214501Srpaulo	wpa_snprintf_hex(pmkid_txt, sizeof(pmkid_txt),
4150214501Srpaulo			 wpa_auth->dot11RSNAPMKIDUsed, PMKID_LEN);
4151214501Srpaulo
4152214501Srpaulo	ret = os_snprintf(
4153214501Srpaulo		buf + len, buflen - len,
4154214501Srpaulo		"dot11RSNAConfigVersion=%u\n"
4155214501Srpaulo		"dot11RSNAConfigPairwiseKeysSupported=9999\n"
4156214501Srpaulo		/* FIX: dot11RSNAConfigGroupCipher */
4157214501Srpaulo		/* FIX: dot11RSNAConfigGroupRekeyMethod */
4158214501Srpaulo		/* FIX: dot11RSNAConfigGroupRekeyTime */
4159214501Srpaulo		/* FIX: dot11RSNAConfigGroupRekeyPackets */
4160214501Srpaulo		"dot11RSNAConfigGroupRekeyStrict=%u\n"
4161214501Srpaulo		"dot11RSNAConfigGroupUpdateCount=%u\n"
4162214501Srpaulo		"dot11RSNAConfigPairwiseUpdateCount=%u\n"
4163214501Srpaulo		"dot11RSNAConfigGroupCipherSize=%u\n"
4164214501Srpaulo		"dot11RSNAConfigPMKLifetime=%u\n"
4165214501Srpaulo		"dot11RSNAConfigPMKReauthThreshold=%u\n"
4166214501Srpaulo		"dot11RSNAConfigNumberOfPTKSAReplayCounters=0\n"
4167214501Srpaulo		"dot11RSNAConfigSATimeout=%u\n"
4168214501Srpaulo		"dot11RSNAAuthenticationSuiteSelected=" RSN_SUITE "\n"
4169214501Srpaulo		"dot11RSNAPairwiseCipherSelected=" RSN_SUITE "\n"
4170214501Srpaulo		"dot11RSNAGroupCipherSelected=" RSN_SUITE "\n"
4171214501Srpaulo		"dot11RSNAPMKIDUsed=%s\n"
4172214501Srpaulo		"dot11RSNAAuthenticationSuiteRequested=" RSN_SUITE "\n"
4173214501Srpaulo		"dot11RSNAPairwiseCipherRequested=" RSN_SUITE "\n"
4174214501Srpaulo		"dot11RSNAGroupCipherRequested=" RSN_SUITE "\n"
4175214501Srpaulo		"dot11RSNATKIPCounterMeasuresInvoked=%u\n"
4176214501Srpaulo		"dot11RSNA4WayHandshakeFailures=%u\n"
4177214501Srpaulo		"dot11RSNAConfigNumberOfGTKSAReplayCounters=0\n",
4178214501Srpaulo		RSN_VERSION,
4179214501Srpaulo		!!wpa_auth->conf.wpa_strict_rekey,
4180346981Scy		wpa_auth->conf.wpa_group_update_count,
4181346981Scy		wpa_auth->conf.wpa_pairwise_update_count,
4182252726Srpaulo		wpa_cipher_key_len(wpa_auth->conf.wpa_group) * 8,
4183214501Srpaulo		dot11RSNAConfigPMKLifetime,
4184214501Srpaulo		dot11RSNAConfigPMKReauthThreshold,
4185214501Srpaulo		dot11RSNAConfigSATimeout,
4186214501Srpaulo		RSN_SUITE_ARG(wpa_auth->dot11RSNAAuthenticationSuiteSelected),
4187214501Srpaulo		RSN_SUITE_ARG(wpa_auth->dot11RSNAPairwiseCipherSelected),
4188214501Srpaulo		RSN_SUITE_ARG(wpa_auth->dot11RSNAGroupCipherSelected),
4189214501Srpaulo		pmkid_txt,
4190214501Srpaulo		RSN_SUITE_ARG(wpa_auth->dot11RSNAAuthenticationSuiteRequested),
4191214501Srpaulo		RSN_SUITE_ARG(wpa_auth->dot11RSNAPairwiseCipherRequested),
4192214501Srpaulo		RSN_SUITE_ARG(wpa_auth->dot11RSNAGroupCipherRequested),
4193214501Srpaulo		wpa_auth->dot11RSNATKIPCounterMeasuresInvoked,
4194214501Srpaulo		wpa_auth->dot11RSNA4WayHandshakeFailures);
4195281806Srpaulo	if (os_snprintf_error(buflen - len, ret))
4196214501Srpaulo		return len;
4197214501Srpaulo	len += ret;
4198214501Srpaulo
4199214501Srpaulo	/* TODO: dot11RSNAConfigPairwiseCiphersTable */
4200214501Srpaulo	/* TODO: dot11RSNAConfigAuthenticationSuitesTable */
4201214501Srpaulo
4202214501Srpaulo	/* Private MIB */
4203214501Srpaulo	ret = os_snprintf(buf + len, buflen - len, "hostapdWPAGroupState=%d\n",
4204214501Srpaulo			  wpa_auth->group->wpa_group_state);
4205281806Srpaulo	if (os_snprintf_error(buflen - len, ret))
4206214501Srpaulo		return len;
4207214501Srpaulo	len += ret;
4208214501Srpaulo
4209214501Srpaulo	return len;
4210214501Srpaulo}
4211214501Srpaulo
4212214501Srpaulo
4213214501Srpauloint wpa_get_mib_sta(struct wpa_state_machine *sm, char *buf, size_t buflen)
4214214501Srpaulo{
4215214501Srpaulo	int len = 0, ret;
4216214501Srpaulo	u32 pairwise = 0;
4217214501Srpaulo
4218214501Srpaulo	if (sm == NULL)
4219214501Srpaulo		return 0;
4220214501Srpaulo
4221214501Srpaulo	/* TODO: FF-FF-FF-FF-FF-FF entry for broadcast/multicast stats */
4222214501Srpaulo
4223214501Srpaulo	/* dot11RSNAStatsEntry */
4224214501Srpaulo
4225252726Srpaulo	pairwise = wpa_cipher_to_suite(sm->wpa == WPA_VERSION_WPA2 ?
4226252726Srpaulo				       WPA_PROTO_RSN : WPA_PROTO_WPA,
4227252726Srpaulo				       sm->pairwise);
4228252726Srpaulo	if (pairwise == 0)
4229214501Srpaulo		return 0;
4230214501Srpaulo
4231214501Srpaulo	ret = os_snprintf(
4232214501Srpaulo		buf + len, buflen - len,
4233214501Srpaulo		/* TODO: dot11RSNAStatsIndex */
4234214501Srpaulo		"dot11RSNAStatsSTAAddress=" MACSTR "\n"
4235214501Srpaulo		"dot11RSNAStatsVersion=1\n"
4236214501Srpaulo		"dot11RSNAStatsSelectedPairwiseCipher=" RSN_SUITE "\n"
4237214501Srpaulo		/* TODO: dot11RSNAStatsTKIPICVErrors */
4238214501Srpaulo		"dot11RSNAStatsTKIPLocalMICFailures=%u\n"
4239252726Srpaulo		"dot11RSNAStatsTKIPRemoteMICFailures=%u\n"
4240214501Srpaulo		/* TODO: dot11RSNAStatsCCMPReplays */
4241214501Srpaulo		/* TODO: dot11RSNAStatsCCMPDecryptErrors */
4242214501Srpaulo		/* TODO: dot11RSNAStatsTKIPReplays */,
4243214501Srpaulo		MAC2STR(sm->addr),
4244214501Srpaulo		RSN_SUITE_ARG(pairwise),
4245214501Srpaulo		sm->dot11RSNAStatsTKIPLocalMICFailures,
4246214501Srpaulo		sm->dot11RSNAStatsTKIPRemoteMICFailures);
4247281806Srpaulo	if (os_snprintf_error(buflen - len, ret))
4248214501Srpaulo		return len;
4249214501Srpaulo	len += ret;
4250214501Srpaulo
4251214501Srpaulo	/* Private MIB */
4252214501Srpaulo	ret = os_snprintf(buf + len, buflen - len,
4253351611Scy			  "wpa=%d\n"
4254351611Scy			  "AKMSuiteSelector=" RSN_SUITE "\n"
4255214501Srpaulo			  "hostapdWPAPTKState=%d\n"
4256214501Srpaulo			  "hostapdWPAPTKGroupState=%d\n",
4257351611Scy			  sm->wpa,
4258351611Scy			  RSN_SUITE_ARG(wpa_akm_to_suite(sm->wpa_key_mgmt)),
4259214501Srpaulo			  sm->wpa_ptk_state,
4260214501Srpaulo			  sm->wpa_ptk_group_state);
4261281806Srpaulo	if (os_snprintf_error(buflen - len, ret))
4262214501Srpaulo		return len;
4263214501Srpaulo	len += ret;
4264214501Srpaulo
4265214501Srpaulo	return len;
4266214501Srpaulo}
4267214501Srpaulo
4268214501Srpaulo
4269214501Srpaulovoid wpa_auth_countermeasures_start(struct wpa_authenticator *wpa_auth)
4270214501Srpaulo{
4271214501Srpaulo	if (wpa_auth)
4272214501Srpaulo		wpa_auth->dot11RSNATKIPCounterMeasuresInvoked++;
4273214501Srpaulo}
4274214501Srpaulo
4275214501Srpaulo
4276214501Srpauloint wpa_auth_pairwise_set(struct wpa_state_machine *sm)
4277214501Srpaulo{
4278214501Srpaulo	return sm && sm->pairwise_set;
4279214501Srpaulo}
4280214501Srpaulo
4281214501Srpaulo
4282214501Srpauloint wpa_auth_get_pairwise(struct wpa_state_machine *sm)
4283214501Srpaulo{
4284214501Srpaulo	return sm->pairwise;
4285214501Srpaulo}
4286214501Srpaulo
4287214501Srpaulo
4288346981Scyconst u8 * wpa_auth_get_pmk(struct wpa_state_machine *sm, int *len)
4289346981Scy{
4290346981Scy	if (!sm)
4291346981Scy		return NULL;
4292346981Scy	*len = sm->pmk_len;
4293346981Scy	return sm->PMK;
4294346981Scy}
4295346981Scy
4296346981Scy
4297214501Srpauloint wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm)
4298214501Srpaulo{
4299214501Srpaulo	if (sm == NULL)
4300214501Srpaulo		return -1;
4301214501Srpaulo	return sm->wpa_key_mgmt;
4302214501Srpaulo}
4303214501Srpaulo
4304214501Srpaulo
4305214501Srpauloint wpa_auth_sta_wpa_version(struct wpa_state_machine *sm)
4306214501Srpaulo{
4307214501Srpaulo	if (sm == NULL)
4308214501Srpaulo		return 0;
4309214501Srpaulo	return sm->wpa;
4310214501Srpaulo}
4311214501Srpaulo
4312214501Srpaulo
4313324697Sgordonint wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm)
4314324697Sgordon{
4315324697Sgordon	if (!sm || !wpa_key_mgmt_ft(sm->wpa_key_mgmt))
4316324697Sgordon		return 0;
4317324697Sgordon	return sm->tk_already_set;
4318324697Sgordon}
4319324697Sgordon
4320324697Sgordon
4321346981Scyint wpa_auth_sta_fils_tk_already_set(struct wpa_state_machine *sm)
4322346981Scy{
4323346981Scy	if (!sm || !wpa_key_mgmt_fils(sm->wpa_key_mgmt))
4324346981Scy		return 0;
4325346981Scy	return sm->tk_already_set;
4326346981Scy}
4327346981Scy
4328346981Scy
4329214501Srpauloint wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm,
4330214501Srpaulo			     struct rsn_pmksa_cache_entry *entry)
4331214501Srpaulo{
4332214501Srpaulo	if (sm == NULL || sm->pmksa != entry)
4333214501Srpaulo		return -1;
4334214501Srpaulo	sm->pmksa = NULL;
4335214501Srpaulo	return 0;
4336214501Srpaulo}
4337214501Srpaulo
4338214501Srpaulo
4339214501Srpaulostruct rsn_pmksa_cache_entry *
4340214501Srpaulowpa_auth_sta_get_pmksa(struct wpa_state_machine *sm)
4341214501Srpaulo{
4342214501Srpaulo	return sm ? sm->pmksa : NULL;
4343214501Srpaulo}
4344214501Srpaulo
4345214501Srpaulo
4346214501Srpaulovoid wpa_auth_sta_local_mic_failure_report(struct wpa_state_machine *sm)
4347214501Srpaulo{
4348214501Srpaulo	if (sm)
4349214501Srpaulo		sm->dot11RSNAStatsTKIPLocalMICFailures++;
4350214501Srpaulo}
4351214501Srpaulo
4352214501Srpaulo
4353214501Srpauloconst u8 * wpa_auth_get_wpa_ie(struct wpa_authenticator *wpa_auth, size_t *len)
4354214501Srpaulo{
4355214501Srpaulo	if (wpa_auth == NULL)
4356214501Srpaulo		return NULL;
4357214501Srpaulo	*len = wpa_auth->wpa_ie_len;
4358214501Srpaulo	return wpa_auth->wpa_ie;
4359214501Srpaulo}
4360214501Srpaulo
4361214501Srpaulo
4362214501Srpauloint wpa_auth_pmksa_add(struct wpa_state_machine *sm, const u8 *pmk,
4363337817Scy		       unsigned int pmk_len,
4364214501Srpaulo		       int session_timeout, struct eapol_state_machine *eapol)
4365214501Srpaulo{
4366252726Srpaulo	if (sm == NULL || sm->wpa != WPA_VERSION_WPA2 ||
4367252726Srpaulo	    sm->wpa_auth->conf.disable_pmksa_caching)
4368214501Srpaulo		return -1;
4369214501Srpaulo
4370351611Scy#ifdef CONFIG_IEEE80211R_AP
4371351611Scy	if (pmk_len >= 2 * PMK_LEN && wpa_key_mgmt_ft(sm->wpa_key_mgmt) &&
4372351611Scy	    wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) &&
4373351611Scy	    !wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) {
4374351611Scy		/* Cache MPMK/XXKey instead of initial part from MSK */
4375351611Scy		pmk = pmk + PMK_LEN;
4376351611Scy		pmk_len = PMK_LEN;
4377351611Scy	} else
4378351611Scy#endif /* CONFIG_IEEE80211R_AP */
4379346981Scy	if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) {
4380337817Scy		if (pmk_len > PMK_LEN_SUITE_B_192)
4381337817Scy			pmk_len = PMK_LEN_SUITE_B_192;
4382337817Scy	} else if (pmk_len > PMK_LEN) {
4383337817Scy		pmk_len = PMK_LEN;
4384337817Scy	}
4385337817Scy
4386351611Scy	wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK", pmk, pmk_len);
4387337817Scy	if (pmksa_cache_auth_add(sm->wpa_auth->pmksa, pmk, pmk_len, NULL,
4388281806Srpaulo				 sm->PTK.kck, sm->PTK.kck_len,
4389214501Srpaulo				 sm->wpa_auth->addr, sm->addr, session_timeout,
4390214501Srpaulo				 eapol, sm->wpa_key_mgmt))
4391214501Srpaulo		return 0;
4392214501Srpaulo
4393214501Srpaulo	return -1;
4394214501Srpaulo}
4395214501Srpaulo
4396214501Srpaulo
4397214501Srpauloint wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth,
4398214501Srpaulo			       const u8 *pmk, size_t len, const u8 *sta_addr,
4399214501Srpaulo			       int session_timeout,
4400214501Srpaulo			       struct eapol_state_machine *eapol)
4401214501Srpaulo{
4402214501Srpaulo	if (wpa_auth == NULL)
4403214501Srpaulo		return -1;
4404214501Srpaulo
4405351611Scy	wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK from preauth", pmk, len);
4406337817Scy	if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, len, NULL,
4407281806Srpaulo				 NULL, 0,
4408281806Srpaulo				 wpa_auth->addr,
4409214501Srpaulo				 sta_addr, session_timeout, eapol,
4410214501Srpaulo				 WPA_KEY_MGMT_IEEE8021X))
4411214501Srpaulo		return 0;
4412214501Srpaulo
4413214501Srpaulo	return -1;
4414214501Srpaulo}
4415214501Srpaulo
4416214501Srpaulo
4417281806Srpauloint wpa_auth_pmksa_add_sae(struct wpa_authenticator *wpa_auth, const u8 *addr,
4418337817Scy			   const u8 *pmk, const u8 *pmkid)
4419281806Srpaulo{
4420281806Srpaulo	if (wpa_auth->conf.disable_pmksa_caching)
4421281806Srpaulo		return -1;
4422281806Srpaulo
4423351611Scy	wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK from SAE", pmk, PMK_LEN);
4424337817Scy	if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, PMK_LEN, pmkid,
4425281806Srpaulo				 NULL, 0,
4426281806Srpaulo				 wpa_auth->addr, addr, 0, NULL,
4427281806Srpaulo				 WPA_KEY_MGMT_SAE))
4428281806Srpaulo		return 0;
4429281806Srpaulo
4430281806Srpaulo	return -1;
4431281806Srpaulo}
4432281806Srpaulo
4433281806Srpaulo
4434346981Scyvoid wpa_auth_add_sae_pmkid(struct wpa_state_machine *sm, const u8 *pmkid)
4435346981Scy{
4436346981Scy	os_memcpy(sm->pmkid, pmkid, PMKID_LEN);
4437346981Scy	sm->pmkid_set = 1;
4438346981Scy}
4439346981Scy
4440346981Scy
4441346981Scyint wpa_auth_pmksa_add2(struct wpa_authenticator *wpa_auth, const u8 *addr,
4442346981Scy			const u8 *pmk, size_t pmk_len, const u8 *pmkid,
4443346981Scy			int session_timeout, int akmp)
4444346981Scy{
4445346981Scy	if (wpa_auth->conf.disable_pmksa_caching)
4446346981Scy		return -1;
4447346981Scy
4448351611Scy	wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK (2)", pmk, PMK_LEN);
4449346981Scy	if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, pmk_len, pmkid,
4450346981Scy				 NULL, 0, wpa_auth->addr, addr, session_timeout,
4451346981Scy				 NULL, akmp))
4452346981Scy		return 0;
4453346981Scy
4454346981Scy	return -1;
4455346981Scy}
4456346981Scy
4457346981Scy
4458281806Srpaulovoid wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth,
4459281806Srpaulo			   const u8 *sta_addr)
4460281806Srpaulo{
4461281806Srpaulo	struct rsn_pmksa_cache_entry *pmksa;
4462281806Srpaulo
4463281806Srpaulo	if (wpa_auth == NULL || wpa_auth->pmksa == NULL)
4464281806Srpaulo		return;
4465281806Srpaulo	pmksa = pmksa_cache_auth_get(wpa_auth->pmksa, sta_addr, NULL);
4466281806Srpaulo	if (pmksa) {
4467281806Srpaulo		wpa_printf(MSG_DEBUG, "WPA: Remove PMKSA cache entry for "
4468281806Srpaulo			   MACSTR " based on request", MAC2STR(sta_addr));
4469281806Srpaulo		pmksa_cache_free_entry(wpa_auth->pmksa, pmksa);
4470281806Srpaulo	}
4471281806Srpaulo}
4472281806Srpaulo
4473281806Srpaulo
4474337817Scyint wpa_auth_pmksa_list(struct wpa_authenticator *wpa_auth, char *buf,
4475337817Scy			size_t len)
4476337817Scy{
4477337817Scy	if (!wpa_auth || !wpa_auth->pmksa)
4478337817Scy		return 0;
4479337817Scy	return pmksa_cache_auth_list(wpa_auth->pmksa, buf, len);
4480337817Scy}
4481337817Scy
4482337817Scy
4483337817Scyvoid wpa_auth_pmksa_flush(struct wpa_authenticator *wpa_auth)
4484337817Scy{
4485337817Scy	if (wpa_auth && wpa_auth->pmksa)
4486337817Scy		pmksa_cache_auth_flush(wpa_auth->pmksa);
4487337817Scy}
4488337817Scy
4489337817Scy
4490346981Scy#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
4491346981Scy#ifdef CONFIG_MESH
4492346981Scy
4493346981Scyint wpa_auth_pmksa_list_mesh(struct wpa_authenticator *wpa_auth, const u8 *addr,
4494346981Scy			     char *buf, size_t len)
4495346981Scy{
4496346981Scy	if (!wpa_auth || !wpa_auth->pmksa)
4497346981Scy		return 0;
4498346981Scy
4499346981Scy	return pmksa_cache_auth_list_mesh(wpa_auth->pmksa, addr, buf, len);
4500346981Scy}
4501346981Scy
4502346981Scy
4503337817Scystruct rsn_pmksa_cache_entry *
4504346981Scywpa_auth_pmksa_create_entry(const u8 *aa, const u8 *spa, const u8 *pmk,
4505346981Scy			    const u8 *pmkid, int expiration)
4506337817Scy{
4507346981Scy	struct rsn_pmksa_cache_entry *entry;
4508346981Scy	struct os_reltime now;
4509346981Scy
4510346981Scy	entry = pmksa_cache_auth_create_entry(pmk, PMK_LEN, pmkid, NULL, 0, aa,
4511346981Scy					      spa, 0, NULL, WPA_KEY_MGMT_SAE);
4512346981Scy	if (!entry)
4513346981Scy		return NULL;
4514346981Scy
4515346981Scy	os_get_reltime(&now);
4516346981Scy	entry->expiration = now.sec + expiration;
4517346981Scy	return entry;
4518346981Scy}
4519346981Scy
4520346981Scy
4521346981Scyint wpa_auth_pmksa_add_entry(struct wpa_authenticator *wpa_auth,
4522346981Scy			     struct rsn_pmksa_cache_entry *entry)
4523346981Scy{
4524346981Scy	int ret;
4525346981Scy
4526337817Scy	if (!wpa_auth || !wpa_auth->pmksa)
4527346981Scy		return -1;
4528346981Scy
4529346981Scy	ret = pmksa_cache_auth_add_entry(wpa_auth->pmksa, entry);
4530346981Scy	if (ret < 0)
4531346981Scy		wpa_printf(MSG_DEBUG,
4532346981Scy			   "RSN: Failed to store external PMKSA cache for "
4533346981Scy			   MACSTR, MAC2STR(entry->spa));
4534346981Scy
4535346981Scy	return ret;
4536346981Scy}
4537346981Scy
4538346981Scy#endif /* CONFIG_MESH */
4539346981Scy#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
4540346981Scy
4541346981Scy
4542346981Scystruct rsn_pmksa_cache_entry *
4543346981Scywpa_auth_pmksa_get(struct wpa_authenticator *wpa_auth, const u8 *sta_addr,
4544346981Scy		   const u8 *pmkid)
4545346981Scy{
4546346981Scy	if (!wpa_auth || !wpa_auth->pmksa)
4547337817Scy		return NULL;
4548346981Scy	return pmksa_cache_auth_get(wpa_auth->pmksa, sta_addr, pmkid);
4549337817Scy}
4550337817Scy
4551337817Scy
4552337817Scyvoid wpa_auth_pmksa_set_to_sm(struct rsn_pmksa_cache_entry *pmksa,
4553337817Scy			      struct wpa_state_machine *sm,
4554337817Scy			      struct wpa_authenticator *wpa_auth,
4555337817Scy			      u8 *pmkid, u8 *pmk)
4556337817Scy{
4557337817Scy	if (!sm)
4558337817Scy		return;
4559337817Scy
4560337817Scy	sm->pmksa = pmksa;
4561337817Scy	os_memcpy(pmk, pmksa->pmk, PMK_LEN);
4562337817Scy	os_memcpy(pmkid, pmksa->pmkid, PMKID_LEN);
4563337817Scy	os_memcpy(wpa_auth->dot11RSNAPMKIDUsed, pmksa->pmkid, PMKID_LEN);
4564337817Scy}
4565337817Scy
4566337817Scy
4567289549Srpaulo/*
4568289549Srpaulo * Remove and free the group from wpa_authenticator. This is triggered by a
4569289549Srpaulo * callback to make sure nobody is currently iterating the group list while it
4570289549Srpaulo * gets modified.
4571289549Srpaulo */
4572289549Srpaulostatic void wpa_group_free(struct wpa_authenticator *wpa_auth,
4573289549Srpaulo			   struct wpa_group *group)
4574289549Srpaulo{
4575289549Srpaulo	struct wpa_group *prev = wpa_auth->group;
4576289549Srpaulo
4577289549Srpaulo	wpa_printf(MSG_DEBUG, "WPA: Remove group state machine for VLAN-ID %d",
4578289549Srpaulo		   group->vlan_id);
4579289549Srpaulo
4580289549Srpaulo	while (prev) {
4581289549Srpaulo		if (prev->next == group) {
4582289549Srpaulo			/* This never frees the special first group as needed */
4583289549Srpaulo			prev->next = group->next;
4584289549Srpaulo			os_free(group);
4585289549Srpaulo			break;
4586289549Srpaulo		}
4587289549Srpaulo		prev = prev->next;
4588289549Srpaulo	}
4589289549Srpaulo
4590289549Srpaulo}
4591289549Srpaulo
4592289549Srpaulo
4593289549Srpaulo/* Increase the reference counter for group */
4594289549Srpaulostatic void wpa_group_get(struct wpa_authenticator *wpa_auth,
4595289549Srpaulo			  struct wpa_group *group)
4596289549Srpaulo{
4597289549Srpaulo	/* Skip the special first group */
4598289549Srpaulo	if (wpa_auth->group == group)
4599289549Srpaulo		return;
4600289549Srpaulo
4601289549Srpaulo	group->references++;
4602289549Srpaulo}
4603289549Srpaulo
4604289549Srpaulo
4605289549Srpaulo/* Decrease the reference counter and maybe free the group */
4606289549Srpaulostatic void wpa_group_put(struct wpa_authenticator *wpa_auth,
4607289549Srpaulo			  struct wpa_group *group)
4608289549Srpaulo{
4609289549Srpaulo	/* Skip the special first group */
4610289549Srpaulo	if (wpa_auth->group == group)
4611289549Srpaulo		return;
4612289549Srpaulo
4613289549Srpaulo	group->references--;
4614289549Srpaulo	if (group->references)
4615289549Srpaulo		return;
4616289549Srpaulo	wpa_group_free(wpa_auth, group);
4617289549Srpaulo}
4618289549Srpaulo
4619289549Srpaulo
4620289549Srpaulo/*
4621289549Srpaulo * Add a group that has its references counter set to zero. Caller needs to
4622289549Srpaulo * call wpa_group_get() on the return value to mark the entry in use.
4623289549Srpaulo */
4624214501Srpaulostatic struct wpa_group *
4625214501Srpaulowpa_auth_add_group(struct wpa_authenticator *wpa_auth, int vlan_id)
4626214501Srpaulo{
4627214501Srpaulo	struct wpa_group *group;
4628214501Srpaulo
4629214501Srpaulo	if (wpa_auth == NULL || wpa_auth->group == NULL)
4630214501Srpaulo		return NULL;
4631214501Srpaulo
4632214501Srpaulo	wpa_printf(MSG_DEBUG, "WPA: Add group state machine for VLAN-ID %d",
4633214501Srpaulo		   vlan_id);
4634252726Srpaulo	group = wpa_group_init(wpa_auth, vlan_id, 0);
4635214501Srpaulo	if (group == NULL)
4636214501Srpaulo		return NULL;
4637214501Srpaulo
4638214501Srpaulo	group->next = wpa_auth->group->next;
4639214501Srpaulo	wpa_auth->group->next = group;
4640214501Srpaulo
4641214501Srpaulo	return group;
4642214501Srpaulo}
4643214501Srpaulo
4644214501Srpaulo
4645337817Scy/*
4646337817Scy * Enforce that the group state machine for the VLAN is running, increase
4647337817Scy * reference counter as interface is up. References might have been increased
4648337817Scy * even if a negative value is returned.
4649337817Scy * Returns: -1 on error (group missing, group already failed); otherwise, 0
4650337817Scy */
4651337817Scyint wpa_auth_ensure_group(struct wpa_authenticator *wpa_auth, int vlan_id)
4652337817Scy{
4653337817Scy	struct wpa_group *group;
4654337817Scy
4655337817Scy	if (wpa_auth == NULL)
4656337817Scy		return 0;
4657337817Scy
4658337817Scy	group = wpa_auth->group;
4659337817Scy	while (group) {
4660337817Scy		if (group->vlan_id == vlan_id)
4661337817Scy			break;
4662337817Scy		group = group->next;
4663337817Scy	}
4664337817Scy
4665337817Scy	if (group == NULL) {
4666337817Scy		group = wpa_auth_add_group(wpa_auth, vlan_id);
4667337817Scy		if (group == NULL)
4668337817Scy			return -1;
4669337817Scy	}
4670337817Scy
4671337817Scy	wpa_printf(MSG_DEBUG,
4672337817Scy		   "WPA: Ensure group state machine running for VLAN ID %d",
4673337817Scy		   vlan_id);
4674337817Scy
4675337817Scy	wpa_group_get(wpa_auth, group);
4676337817Scy	group->num_setup_iface++;
4677337817Scy
4678337817Scy	if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
4679337817Scy		return -1;
4680337817Scy
4681337817Scy	return 0;
4682337817Scy}
4683337817Scy
4684337817Scy
4685337817Scy/*
4686337817Scy * Decrease reference counter, expected to be zero afterwards.
4687337817Scy * returns: -1 on error (group not found, group in fail state)
4688337817Scy *          -2 if wpa_group is still referenced
4689337817Scy *           0 else
4690337817Scy */
4691337817Scyint wpa_auth_release_group(struct wpa_authenticator *wpa_auth, int vlan_id)
4692337817Scy{
4693337817Scy	struct wpa_group *group;
4694337817Scy	int ret = 0;
4695337817Scy
4696337817Scy	if (wpa_auth == NULL)
4697337817Scy		return 0;
4698337817Scy
4699337817Scy	group = wpa_auth->group;
4700337817Scy	while (group) {
4701337817Scy		if (group->vlan_id == vlan_id)
4702337817Scy			break;
4703337817Scy		group = group->next;
4704337817Scy	}
4705337817Scy
4706337817Scy	if (group == NULL)
4707337817Scy		return -1;
4708337817Scy
4709337817Scy	wpa_printf(MSG_DEBUG,
4710337817Scy		   "WPA: Try stopping group state machine for VLAN ID %d",
4711337817Scy		   vlan_id);
4712337817Scy
4713337817Scy	if (group->num_setup_iface <= 0) {
4714337817Scy		wpa_printf(MSG_ERROR,
4715337817Scy			   "WPA: wpa_auth_release_group called more often than wpa_auth_ensure_group for VLAN ID %d, skipping.",
4716337817Scy			   vlan_id);
4717337817Scy		return -1;
4718337817Scy	}
4719337817Scy	group->num_setup_iface--;
4720337817Scy
4721337817Scy	if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
4722337817Scy		ret = -1;
4723337817Scy
4724337817Scy	if (group->references > 1) {
4725337817Scy		wpa_printf(MSG_DEBUG,
4726337817Scy			   "WPA: Cannot stop group state machine for VLAN ID %d as references are still hold",
4727337817Scy			   vlan_id);
4728337817Scy		ret = -2;
4729337817Scy	}
4730337817Scy
4731337817Scy	wpa_group_put(wpa_auth, group);
4732337817Scy
4733337817Scy	return ret;
4734337817Scy}
4735337817Scy
4736337817Scy
4737214501Srpauloint wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id)
4738214501Srpaulo{
4739214501Srpaulo	struct wpa_group *group;
4740214501Srpaulo
4741214501Srpaulo	if (sm == NULL || sm->wpa_auth == NULL)
4742214501Srpaulo		return 0;
4743214501Srpaulo
4744214501Srpaulo	group = sm->wpa_auth->group;
4745214501Srpaulo	while (group) {
4746214501Srpaulo		if (group->vlan_id == vlan_id)
4747214501Srpaulo			break;
4748214501Srpaulo		group = group->next;
4749214501Srpaulo	}
4750214501Srpaulo
4751214501Srpaulo	if (group == NULL) {
4752214501Srpaulo		group = wpa_auth_add_group(sm->wpa_auth, vlan_id);
4753214501Srpaulo		if (group == NULL)
4754214501Srpaulo			return -1;
4755214501Srpaulo	}
4756214501Srpaulo
4757214501Srpaulo	if (sm->group == group)
4758214501Srpaulo		return 0;
4759214501Srpaulo
4760281806Srpaulo	if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
4761281806Srpaulo		return -1;
4762281806Srpaulo
4763214501Srpaulo	wpa_printf(MSG_DEBUG, "WPA: Moving STA " MACSTR " to use group state "
4764214501Srpaulo		   "machine for VLAN ID %d", MAC2STR(sm->addr), vlan_id);
4765214501Srpaulo
4766289549Srpaulo	wpa_group_get(sm->wpa_auth, group);
4767289549Srpaulo	wpa_group_put(sm->wpa_auth, sm->group);
4768214501Srpaulo	sm->group = group;
4769289549Srpaulo
4770214501Srpaulo	return 0;
4771214501Srpaulo}
4772252726Srpaulo
4773252726Srpaulo
4774252726Srpaulovoid wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth,
4775252726Srpaulo				  struct wpa_state_machine *sm, int ack)
4776252726Srpaulo{
4777252726Srpaulo	if (wpa_auth == NULL || sm == NULL)
4778252726Srpaulo		return;
4779252726Srpaulo	wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key TX status for STA " MACSTR
4780252726Srpaulo		   " ack=%d", MAC2STR(sm->addr), ack);
4781252726Srpaulo	if (sm->pending_1_of_4_timeout && ack) {
4782252726Srpaulo		/*
4783252726Srpaulo		 * Some deployed supplicant implementations update their SNonce
4784252726Srpaulo		 * for each EAPOL-Key 2/4 message even within the same 4-way
4785252726Srpaulo		 * handshake and then fail to use the first SNonce when
4786252726Srpaulo		 * deriving the PTK. This results in unsuccessful 4-way
4787252726Srpaulo		 * handshake whenever the relatively short initial timeout is
4788252726Srpaulo		 * reached and EAPOL-Key 1/4 is retransmitted. Try to work
4789252726Srpaulo		 * around this by increasing the timeout now that we know that
4790252726Srpaulo		 * the station has received the frame.
4791252726Srpaulo		 */
4792252726Srpaulo		int timeout_ms = eapol_key_timeout_subseq;
4793252726Srpaulo		wpa_printf(MSG_DEBUG, "WPA: Increase initial EAPOL-Key 1/4 "
4794252726Srpaulo			   "timeout by %u ms because of acknowledged frame",
4795252726Srpaulo			   timeout_ms);
4796252726Srpaulo		eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm);
4797252726Srpaulo		eloop_register_timeout(timeout_ms / 1000,
4798252726Srpaulo				       (timeout_ms % 1000) * 1000,
4799252726Srpaulo				       wpa_send_eapol_timeout, wpa_auth, sm);
4800252726Srpaulo	}
4801346981Scy
4802346981Scy#ifdef CONFIG_TESTING_OPTIONS
4803346981Scy	if (sm->eapol_status_cb) {
4804346981Scy		sm->eapol_status_cb(sm->eapol_status_cb_ctx1,
4805346981Scy				    sm->eapol_status_cb_ctx2);
4806346981Scy		sm->eapol_status_cb = NULL;
4807346981Scy	}
4808346981Scy#endif /* CONFIG_TESTING_OPTIONS */
4809252726Srpaulo}
4810252726Srpaulo
4811252726Srpaulo
4812252726Srpauloint wpa_auth_uses_sae(struct wpa_state_machine *sm)
4813252726Srpaulo{
4814252726Srpaulo	if (sm == NULL)
4815252726Srpaulo		return 0;
4816252726Srpaulo	return wpa_key_mgmt_sae(sm->wpa_key_mgmt);
4817252726Srpaulo}
4818281806Srpaulo
4819281806Srpaulo
4820281806Srpauloint wpa_auth_uses_ft_sae(struct wpa_state_machine *sm)
4821281806Srpaulo{
4822281806Srpaulo	if (sm == NULL)
4823281806Srpaulo		return 0;
4824281806Srpaulo	return sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_SAE;
4825281806Srpaulo}
4826281806Srpaulo
4827281806Srpaulo
4828281806Srpaulo#ifdef CONFIG_P2P
4829281806Srpauloint wpa_auth_get_ip_addr(struct wpa_state_machine *sm, u8 *addr)
4830281806Srpaulo{
4831281806Srpaulo	if (sm == NULL || WPA_GET_BE32(sm->ip_addr) == 0)
4832281806Srpaulo		return -1;
4833281806Srpaulo	os_memcpy(addr, sm->ip_addr, 4);
4834281806Srpaulo	return 0;
4835281806Srpaulo}
4836281806Srpaulo#endif /* CONFIG_P2P */
4837281806Srpaulo
4838281806Srpaulo
4839281806Srpauloint wpa_auth_radius_das_disconnect_pmksa(struct wpa_authenticator *wpa_auth,
4840281806Srpaulo					 struct radius_das_attrs *attr)
4841281806Srpaulo{
4842281806Srpaulo	return pmksa_cache_auth_radius_das_disconnect(wpa_auth->pmksa, attr);
4843281806Srpaulo}
4844281806Srpaulo
4845281806Srpaulo
4846281806Srpaulovoid wpa_auth_reconfig_group_keys(struct wpa_authenticator *wpa_auth)
4847281806Srpaulo{
4848281806Srpaulo	struct wpa_group *group;
4849281806Srpaulo
4850281806Srpaulo	if (!wpa_auth)
4851281806Srpaulo		return;
4852281806Srpaulo	for (group = wpa_auth->group; group; group = group->next)
4853281806Srpaulo		wpa_group_config_group_keys(wpa_auth, group);
4854281806Srpaulo}
4855346981Scy
4856346981Scy
4857346981Scy#ifdef CONFIG_FILS
4858346981Scy
4859346981Scystruct wpa_auth_fils_iter_data {
4860346981Scy	struct wpa_authenticator *auth;
4861346981Scy	const u8 *cache_id;
4862346981Scy	struct rsn_pmksa_cache_entry *pmksa;
4863346981Scy	const u8 *spa;
4864346981Scy	const u8 *pmkid;
4865346981Scy};
4866346981Scy
4867346981Scy
4868346981Scystatic int wpa_auth_fils_iter(struct wpa_authenticator *a, void *ctx)
4869346981Scy{
4870346981Scy	struct wpa_auth_fils_iter_data *data = ctx;
4871346981Scy
4872346981Scy	if (a == data->auth || !a->conf.fils_cache_id_set ||
4873346981Scy	    os_memcmp(a->conf.fils_cache_id, data->cache_id,
4874346981Scy		      FILS_CACHE_ID_LEN) != 0)
4875346981Scy		return 0;
4876346981Scy	data->pmksa = pmksa_cache_auth_get(a->pmksa, data->spa, data->pmkid);
4877346981Scy	return data->pmksa != NULL;
4878346981Scy}
4879346981Scy
4880346981Scy
4881346981Scystruct rsn_pmksa_cache_entry *
4882346981Scywpa_auth_pmksa_get_fils_cache_id(struct wpa_authenticator *wpa_auth,
4883346981Scy				 const u8 *sta_addr, const u8 *pmkid)
4884346981Scy{
4885346981Scy	struct wpa_auth_fils_iter_data idata;
4886346981Scy
4887346981Scy	if (!wpa_auth->conf.fils_cache_id_set)
4888346981Scy		return NULL;
4889346981Scy	idata.auth = wpa_auth;
4890346981Scy	idata.cache_id = wpa_auth->conf.fils_cache_id;
4891346981Scy	idata.pmksa = NULL;
4892346981Scy	idata.spa = sta_addr;
4893346981Scy	idata.pmkid = pmkid;
4894346981Scy	wpa_auth_for_each_auth(wpa_auth, wpa_auth_fils_iter, &idata);
4895346981Scy	return idata.pmksa;
4896346981Scy}
4897346981Scy
4898346981Scy
4899346981Scy#ifdef CONFIG_IEEE80211R_AP
4900346981Scyint wpa_auth_write_fte(struct wpa_authenticator *wpa_auth, int use_sha384,
4901346981Scy		       u8 *buf, size_t len)
4902346981Scy{
4903346981Scy	struct wpa_auth_config *conf = &wpa_auth->conf;
4904346981Scy
4905346981Scy	return wpa_write_ftie(conf, use_sha384, conf->r0_key_holder,
4906346981Scy			      conf->r0_key_holder_len,
4907346981Scy			      NULL, NULL, buf, len, NULL, 0);
4908346981Scy}
4909346981Scy#endif /* CONFIG_IEEE80211R_AP */
4910346981Scy
4911346981Scy
4912346981Scyvoid wpa_auth_get_fils_aead_params(struct wpa_state_machine *sm,
4913346981Scy				   u8 *fils_anonce, u8 *fils_snonce,
4914346981Scy				   u8 *fils_kek, size_t *fils_kek_len)
4915346981Scy{
4916346981Scy	os_memcpy(fils_anonce, sm->ANonce, WPA_NONCE_LEN);
4917346981Scy	os_memcpy(fils_snonce, sm->SNonce, WPA_NONCE_LEN);
4918346981Scy	os_memcpy(fils_kek, sm->PTK.kek, WPA_KEK_MAX_LEN);
4919346981Scy	*fils_kek_len = sm->PTK.kek_len;
4920346981Scy}
4921346981Scy
4922346981Scy
4923346981Scyvoid wpa_auth_add_fils_pmk_pmkid(struct wpa_state_machine *sm, const u8 *pmk,
4924346981Scy				 size_t pmk_len, const u8 *pmkid)
4925346981Scy{
4926346981Scy	os_memcpy(sm->PMK, pmk, pmk_len);
4927346981Scy	sm->pmk_len = pmk_len;
4928346981Scy	os_memcpy(sm->pmkid, pmkid, PMKID_LEN);
4929346981Scy	sm->pmkid_set = 1;
4930346981Scy}
4931346981Scy
4932346981Scy#endif /* CONFIG_FILS */
4933346981Scy
4934346981Scy
4935346981Scyvoid wpa_auth_set_auth_alg(struct wpa_state_machine *sm, u16 auth_alg)
4936346981Scy{
4937346981Scy	if (sm)
4938346981Scy		sm->auth_alg = auth_alg;
4939346981Scy}
4940346981Scy
4941346981Scy
4942346981Scy#ifdef CONFIG_DPP2
4943346981Scyvoid wpa_auth_set_dpp_z(struct wpa_state_machine *sm, const struct wpabuf *z)
4944346981Scy{
4945346981Scy	if (sm) {
4946346981Scy		wpabuf_clear_free(sm->dpp_z);
4947346981Scy		sm->dpp_z = z ? wpabuf_dup(z) : NULL;
4948346981Scy	}
4949346981Scy}
4950346981Scy#endif /* CONFIG_DPP2 */
4951346981Scy
4952346981Scy
4953346981Scy#ifdef CONFIG_TESTING_OPTIONS
4954346981Scy
4955346981Scyint wpa_auth_resend_m1(struct wpa_state_machine *sm, int change_anonce,
4956346981Scy		       void (*cb)(void *ctx1, void *ctx2),
4957346981Scy		       void *ctx1, void *ctx2)
4958346981Scy{
4959346981Scy	const u8 *anonce = sm->ANonce;
4960346981Scy	u8 anonce_buf[WPA_NONCE_LEN];
4961346981Scy
4962346981Scy	if (change_anonce) {
4963346981Scy		if (random_get_bytes(anonce_buf, WPA_NONCE_LEN))
4964346981Scy			return -1;
4965346981Scy		anonce = anonce_buf;
4966346981Scy	}
4967346981Scy
4968346981Scy	wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
4969346981Scy			"sending 1/4 msg of 4-Way Handshake (TESTING)");
4970346981Scy	wpa_send_eapol(sm->wpa_auth, sm,
4971346981Scy		       WPA_KEY_INFO_ACK | WPA_KEY_INFO_KEY_TYPE, NULL,
4972346981Scy		       anonce, NULL, 0, 0, 0);
4973346981Scy	return 0;
4974346981Scy}
4975346981Scy
4976346981Scy
4977346981Scyint wpa_auth_resend_m3(struct wpa_state_machine *sm,
4978346981Scy		       void (*cb)(void *ctx1, void *ctx2),
4979346981Scy		       void *ctx1, void *ctx2)
4980346981Scy{
4981346981Scy	u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde, *pos;
4982346981Scy#ifdef CONFIG_IEEE80211W
4983346981Scy	u8 *opos;
4984346981Scy#endif /* CONFIG_IEEE80211W */
4985346981Scy	size_t gtk_len, kde_len;
4986346981Scy	struct wpa_group *gsm = sm->group;
4987346981Scy	u8 *wpa_ie;
4988346981Scy	int wpa_ie_len, secure, keyidx, encr = 0;
4989346981Scy
4990346981Scy	/* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, [MDIE],
4991346981Scy	   GTK[GN], IGTK, [FTIE], [TIE * 2])
4992346981Scy	 */
4993346981Scy
4994346981Scy	/* Use 0 RSC */
4995346981Scy	os_memset(rsc, 0, WPA_KEY_RSC_LEN);
4996346981Scy	/* If FT is used, wpa_auth->wpa_ie includes both RSNIE and MDIE */
4997346981Scy	wpa_ie = sm->wpa_auth->wpa_ie;
4998346981Scy	wpa_ie_len = sm->wpa_auth->wpa_ie_len;
4999346981Scy	if (sm->wpa == WPA_VERSION_WPA &&
5000346981Scy	    (sm->wpa_auth->conf.wpa & WPA_PROTO_RSN) &&
5001346981Scy	    wpa_ie_len > wpa_ie[1] + 2 && wpa_ie[0] == WLAN_EID_RSN) {
5002346981Scy		/* WPA-only STA, remove RSN IE and possible MDIE */
5003346981Scy		wpa_ie = wpa_ie + wpa_ie[1] + 2;
5004346981Scy		if (wpa_ie[0] == WLAN_EID_MOBILITY_DOMAIN)
5005346981Scy			wpa_ie = wpa_ie + wpa_ie[1] + 2;
5006346981Scy		wpa_ie_len = wpa_ie[1] + 2;
5007346981Scy	}
5008346981Scy	wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
5009346981Scy			"sending 3/4 msg of 4-Way Handshake (TESTING)");
5010346981Scy	if (sm->wpa == WPA_VERSION_WPA2) {
5011346981Scy		/* WPA2 send GTK in the 4-way handshake */
5012346981Scy		secure = 1;
5013346981Scy		gtk = gsm->GTK[gsm->GN - 1];
5014346981Scy		gtk_len = gsm->GTK_len;
5015346981Scy		keyidx = gsm->GN;
5016346981Scy		_rsc = rsc;
5017346981Scy		encr = 1;
5018346981Scy	} else {
5019346981Scy		/* WPA does not include GTK in msg 3/4 */
5020346981Scy		secure = 0;
5021346981Scy		gtk = NULL;
5022346981Scy		gtk_len = 0;
5023346981Scy		keyidx = 0;
5024346981Scy		_rsc = NULL;
5025346981Scy		if (sm->rx_eapol_key_secure) {
5026346981Scy			/*
5027346981Scy			 * It looks like Windows 7 supplicant tries to use
5028346981Scy			 * Secure bit in msg 2/4 after having reported Michael
5029346981Scy			 * MIC failure and it then rejects the 4-way handshake
5030346981Scy			 * if msg 3/4 does not set Secure bit. Work around this
5031346981Scy			 * by setting the Secure bit here even in the case of
5032346981Scy			 * WPA if the supplicant used it first.
5033346981Scy			 */
5034346981Scy			wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
5035346981Scy					"STA used Secure bit in WPA msg 2/4 - "
5036346981Scy					"set Secure for 3/4 as workaround");
5037346981Scy			secure = 1;
5038346981Scy		}
5039346981Scy	}
5040346981Scy
5041346981Scy	kde_len = wpa_ie_len + ieee80211w_kde_len(sm) + ocv_oci_len(sm);
5042346981Scy	if (gtk)
5043346981Scy		kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len;
5044346981Scy#ifdef CONFIG_IEEE80211R_AP
5045346981Scy	if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
5046346981Scy		kde_len += 2 + PMKID_LEN; /* PMKR1Name into RSN IE */
5047346981Scy		kde_len += 300; /* FTIE + 2 * TIE */
5048346981Scy	}
5049346981Scy#endif /* CONFIG_IEEE80211R_AP */
5050346981Scy	kde = os_malloc(kde_len);
5051346981Scy	if (kde == NULL)
5052346981Scy		return -1;
5053346981Scy
5054346981Scy	pos = kde;
5055346981Scy	os_memcpy(pos, wpa_ie, wpa_ie_len);
5056346981Scy	pos += wpa_ie_len;
5057346981Scy#ifdef CONFIG_IEEE80211R_AP
5058346981Scy	if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
5059346981Scy		int res;
5060346981Scy		size_t elen;
5061346981Scy
5062346981Scy		elen = pos - kde;
5063346981Scy		res = wpa_insert_pmkid(kde, &elen, sm->pmk_r1_name);
5064346981Scy		if (res < 0) {
5065346981Scy			wpa_printf(MSG_ERROR, "FT: Failed to insert "
5066346981Scy				   "PMKR1Name into RSN IE in EAPOL-Key data");
5067346981Scy			os_free(kde);
5068346981Scy			return -1;
5069346981Scy		}
5070346981Scy		pos -= wpa_ie_len;
5071346981Scy		pos += elen;
5072346981Scy	}
5073346981Scy#endif /* CONFIG_IEEE80211R_AP */
5074346981Scy	if (gtk) {
5075346981Scy		u8 hdr[2];
5076346981Scy		hdr[0] = keyidx & 0x03;
5077346981Scy		hdr[1] = 0;
5078346981Scy		pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
5079346981Scy				  gtk, gtk_len);
5080346981Scy	}
5081346981Scy#ifdef CONFIG_IEEE80211W
5082346981Scy	opos = pos;
5083346981Scy	pos = ieee80211w_kde_add(sm, pos);
5084346981Scy	if (pos - opos >= 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN) {
5085346981Scy		/* skip KDE header and keyid */
5086346981Scy		opos += 2 + RSN_SELECTOR_LEN + 2;
5087346981Scy		os_memset(opos, 0, 6); /* clear PN */
5088346981Scy	}
5089346981Scy#endif /* CONFIG_IEEE80211W */
5090346981Scy	if (ocv_oci_add(sm, &pos) < 0) {
5091346981Scy		os_free(kde);
5092346981Scy		return -1;
5093346981Scy	}
5094346981Scy
5095346981Scy#ifdef CONFIG_IEEE80211R_AP
5096346981Scy	if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
5097346981Scy		int res;
5098346981Scy		struct wpa_auth_config *conf;
5099346981Scy
5100346981Scy		conf = &sm->wpa_auth->conf;
5101346981Scy		if (sm->assoc_resp_ftie &&
5102346981Scy		    kde + kde_len - pos >= 2 + sm->assoc_resp_ftie[1]) {
5103346981Scy			os_memcpy(pos, sm->assoc_resp_ftie,
5104346981Scy				  2 + sm->assoc_resp_ftie[1]);
5105346981Scy			res = 2 + sm->assoc_resp_ftie[1];
5106346981Scy		} else {
5107346981Scy			int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt);
5108346981Scy
5109346981Scy			res = wpa_write_ftie(conf, use_sha384,
5110346981Scy					     conf->r0_key_holder,
5111346981Scy					     conf->r0_key_holder_len,
5112346981Scy					     NULL, NULL, pos,
5113346981Scy					     kde + kde_len - pos,
5114346981Scy					     NULL, 0);
5115346981Scy		}
5116346981Scy		if (res < 0) {
5117346981Scy			wpa_printf(MSG_ERROR, "FT: Failed to insert FTIE "
5118346981Scy				   "into EAPOL-Key Key Data");
5119346981Scy			os_free(kde);
5120346981Scy			return -1;
5121346981Scy		}
5122346981Scy		pos += res;
5123346981Scy
5124346981Scy		/* TIE[ReassociationDeadline] (TU) */
5125346981Scy		*pos++ = WLAN_EID_TIMEOUT_INTERVAL;
5126346981Scy		*pos++ = 5;
5127346981Scy		*pos++ = WLAN_TIMEOUT_REASSOC_DEADLINE;
5128346981Scy		WPA_PUT_LE32(pos, conf->reassociation_deadline);
5129346981Scy		pos += 4;
5130346981Scy
5131346981Scy		/* TIE[KeyLifetime] (seconds) */
5132346981Scy		*pos++ = WLAN_EID_TIMEOUT_INTERVAL;
5133346981Scy		*pos++ = 5;
5134346981Scy		*pos++ = WLAN_TIMEOUT_KEY_LIFETIME;
5135346981Scy		WPA_PUT_LE32(pos, conf->r0_key_lifetime);
5136346981Scy		pos += 4;
5137346981Scy	}
5138346981Scy#endif /* CONFIG_IEEE80211R_AP */
5139346981Scy
5140346981Scy	wpa_send_eapol(sm->wpa_auth, sm,
5141346981Scy		       (secure ? WPA_KEY_INFO_SECURE : 0) |
5142346981Scy		       (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
5143346981Scy			WPA_KEY_INFO_MIC : 0) |
5144346981Scy		       WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL |
5145346981Scy		       WPA_KEY_INFO_KEY_TYPE,
5146346981Scy		       _rsc, sm->ANonce, kde, pos - kde, keyidx, encr);
5147346981Scy	os_free(kde);
5148346981Scy	return 0;
5149346981Scy}
5150346981Scy
5151346981Scy
5152346981Scyint wpa_auth_resend_group_m1(struct wpa_state_machine *sm,
5153346981Scy			     void (*cb)(void *ctx1, void *ctx2),
5154346981Scy			     void *ctx1, void *ctx2)
5155346981Scy{
5156346981Scy	u8 rsc[WPA_KEY_RSC_LEN];
5157346981Scy	struct wpa_group *gsm = sm->group;
5158346981Scy	const u8 *kde;
5159346981Scy	u8 *kde_buf = NULL, *pos, hdr[2];
5160346981Scy#ifdef CONFIG_IEEE80211W
5161346981Scy	u8 *opos;
5162346981Scy#endif /* CONFIG_IEEE80211W */
5163346981Scy	size_t kde_len;
5164346981Scy	u8 *gtk;
5165346981Scy
5166346981Scy	/* Send EAPOL(1, 1, 1, !Pair, G, RSC, GNonce, MIC(PTK), GTK[GN]) */
5167346981Scy	os_memset(rsc, 0, WPA_KEY_RSC_LEN);
5168346981Scy	/* Use 0 RSC */
5169346981Scy	wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
5170346981Scy			"sending 1/2 msg of Group Key Handshake (TESTING)");
5171346981Scy
5172346981Scy	gtk = gsm->GTK[gsm->GN - 1];
5173346981Scy	if (sm->wpa == WPA_VERSION_WPA2) {
5174346981Scy		kde_len = 2 + RSN_SELECTOR_LEN + 2 + gsm->GTK_len +
5175346981Scy			ieee80211w_kde_len(sm) + ocv_oci_len(sm);
5176346981Scy		kde_buf = os_malloc(kde_len);
5177346981Scy		if (kde_buf == NULL)
5178346981Scy			return -1;
5179346981Scy
5180346981Scy		kde = pos = kde_buf;
5181346981Scy		hdr[0] = gsm->GN & 0x03;
5182346981Scy		hdr[1] = 0;
5183346981Scy		pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2,
5184346981Scy				  gtk, gsm->GTK_len);
5185346981Scy#ifdef CONFIG_IEEE80211W
5186346981Scy		opos = pos;
5187346981Scy		pos = ieee80211w_kde_add(sm, pos);
5188346981Scy		if (pos - opos >=
5189346981Scy		    2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN) {
5190346981Scy			/* skip KDE header and keyid */
5191346981Scy			opos += 2 + RSN_SELECTOR_LEN + 2;
5192346981Scy			os_memset(opos, 0, 6); /* clear PN */
5193346981Scy		}
5194346981Scy#endif /* CONFIG_IEEE80211W */
5195346981Scy		if (ocv_oci_add(sm, &pos) < 0) {
5196346981Scy			os_free(kde_buf);
5197346981Scy			return -1;
5198346981Scy		}
5199346981Scy		kde_len = pos - kde;
5200346981Scy	} else {
5201346981Scy		kde = gtk;
5202346981Scy		kde_len = gsm->GTK_len;
5203346981Scy	}
5204346981Scy
5205346981Scy	sm->eapol_status_cb = cb;
5206346981Scy	sm->eapol_status_cb_ctx1 = ctx1;
5207346981Scy	sm->eapol_status_cb_ctx2 = ctx2;
5208346981Scy
5209346981Scy	wpa_send_eapol(sm->wpa_auth, sm,
5210346981Scy		       WPA_KEY_INFO_SECURE |
5211346981Scy		       (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
5212346981Scy			WPA_KEY_INFO_MIC : 0) |
5213346981Scy		       WPA_KEY_INFO_ACK |
5214346981Scy		       (!sm->Pair ? WPA_KEY_INFO_INSTALL : 0),
5215346981Scy		       rsc, NULL, kde, kde_len, gsm->GN, 1);
5216346981Scy
5217346981Scy	os_free(kde_buf);
5218346981Scy	return 0;
5219346981Scy}
5220346981Scy
5221346981Scy
5222346981Scyint wpa_auth_rekey_gtk(struct wpa_authenticator *wpa_auth)
5223346981Scy{
5224346981Scy	if (!wpa_auth)
5225346981Scy		return -1;
5226346981Scy	eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL);
5227346981Scy	return eloop_register_timeout(0, 0, wpa_rekey_gtk, wpa_auth, NULL);
5228346981Scy}
5229346981Scy
5230346981Scy#endif /* CONFIG_TESTING_OPTIONS */
5231