18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPA Supplicant - WPA state machine and EAPOL-Key processing
3c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/aes_wrap.h"
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/crypto.h"
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/random.h"
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_defs.h"
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eapol_supp/eapol_supp_sm.h"
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa.h"
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eloop.h"
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "preauth.h"
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "pmksa_cache.h"
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_i.h"
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_ie.h"
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "peerkey.h"
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_eapol_key_send - Send WPA/RSN EAPOL-Key message
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @kck: Key Confirmation Key (KCK, part of PTK)
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ver: Version field from Key Info
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @dest: Destination address for the frame
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @proto: Ethertype (usually ETH_P_EAPOL)
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @msg: EAPOL-Key message
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @msg_len: Length of message
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @key_mic: Pointer to the buffer to which the EAPOL-Key MIC is written
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck,
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			int ver, const u8 *dest, u16 proto,
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u8 *msg, size_t msg_len, u8 *key_mic)
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (is_zero_ether_addr(dest) && is_zero_ether_addr(sm->bssid)) {
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Association event was not yet received; try to fetch
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * BSSID from the driver.
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_sm_get_bssid(sm, sm->bssid) < 0) {
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Failed to read BSSID for "
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"EAPOL-Key destination address");
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dest = sm->bssid;
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Use BSSID (" MACSTR
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				") as the destination for EAPOL-Key",
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MAC2STR(dest));
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (key_mic &&
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wpa_eapol_key_mic(kck, ver, msg, msg_len, key_mic)) {
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: Failed to generate EAPOL-Key "
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"version %d MIC", ver);
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_key(MSG_DEBUG, "WPA: KCK", kck, 16);
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "WPA: Derived Key MIC", key_mic, 16);
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "WPA: TX EAPOL-Key", msg, msg_len);
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_sm_ether_send(sm, dest, proto, msg, msg_len);
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_sm_notify_tx_eapol_key(sm->eapol);
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtout:
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(msg);
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_key_request - Send EAPOL-Key Request
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @error: Indicate whether this is an Michael MIC error report
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pairwise: 1 = error report for pairwise packet, 0 = for group packet
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Send an EAPOL-Key Request to the current authenticator. This function is
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * used to request rekeying and it is usually called when a local Michael MIC
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * failure is detected.
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise)
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t rlen;
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_eapol_key *reply;
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int key_info, ver;
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 bssid[ETH_ALEN], *rbuf;
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
92f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	if (sm->key_mgmt == WPA_KEY_MGMT_OSEN)
93f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		ver = WPA_KEY_INFO_TYPE_AKM_DEFINED;
94f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	else if (wpa_key_mgmt_ft(sm->key_mgmt) ||
95f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		 wpa_key_mgmt_sha256(sm->key_mgmt))
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ver = WPA_KEY_INFO_TYPE_AES_128_CMAC;
9761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	else if (sm->pairwise_cipher != WPA_CIPHER_TKIP)
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_sm_get_bssid(sm, bssid) < 0) {
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Failed to read BSSID for EAPOL-Key request");
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  sizeof(*reply), &rlen, (void *) &reply);
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (rbuf == NULL)
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
113f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	reply->type = (sm->proto == WPA_PROTO_RSN ||
114f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		       sm->proto == WPA_PROTO_OSEN) ?
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key_info = WPA_KEY_INFO_REQUEST | ver;
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->ptk_set)
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_info |= WPA_KEY_INFO_MIC;
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (error)
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_info |= WPA_KEY_INFO_ERROR;
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pairwise)
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_info |= WPA_KEY_INFO_KEY_TYPE;
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE16(reply->key_info, key_info);
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE16(reply->key_length, 0);
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(reply->replay_counter, sm->request_counter,
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  WPA_REPLAY_COUNTER_LEN);
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN);
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE16(reply->key_data_length, 0);
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"WPA: Sending EAPOL-Key Request (error=%d "
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"pairwise=%d ptk_set=%d len=%lu)",
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		error, pairwise, sm->ptk_set, (unsigned long) rlen);
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_eapol_key_send(sm, sm->ptk.kck, ver, bssid, ETH_P_EAPOL,
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   rbuf, rlen, key_info & WPA_KEY_INFO_MIC ?
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   reply->key_mic : NULL);
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_get_pmk(struct wpa_sm *sm,
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  const unsigned char *src_addr,
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  const u8 *pmkid)
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int abort_cached = 0;
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pmkid && !sm->cur_pmksa) {
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* When using drivers that generate RSN IE, wpa_supplicant may
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * not have enough time to get the association information
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * event before receiving this 1/4 message, so try to find a
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * matching PMKSA cache entry here. */
152c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		sm->cur_pmksa = pmksa_cache_get(sm->pmksa, src_addr, pmkid,
153c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt						NULL);
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->cur_pmksa) {
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"RSN: found matching PMKID from PMKSA cache");
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"RSN: no matching PMKID found");
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			abort_cached = 1;
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pmkid && sm->cur_pmksa &&
165c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt	    os_memcmp_const(pmkid, sm->cur_pmksa->pmkid, PMKID_LEN) == 0) {
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "RSN: matched PMKID", pmkid, PMKID_LEN);
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_sm_set_pmk_from_pmksa(sm);
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump_key(MSG_DEBUG, "RSN: PMK from PMKSA cache",
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				sm->pmk, sm->pmk_len);
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eapol_sm_notify_cached(sm->eapol);
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->xxkey_len = 0;
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt) && sm->eapol) {
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int res, pmk_len;
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pmk_len = PMK_LEN;
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = eapol_sm_get_key(sm->eapol, sm->pmk, PMK_LEN);
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res) {
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/*
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * EAP-LEAP is an exception from other EAP methods: it
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * uses only 16-byte PMK.
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 */
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			res = eapol_sm_get_key(sm->eapol, sm->pmk, 16);
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pmk_len = 16;
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u8 buf[2 * PMK_LEN];
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (eapol_sm_get_key(sm->eapol, buf, 2 * PMK_LEN) == 0)
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			{
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				os_memcpy(sm->xxkey, buf + PMK_LEN, PMK_LEN);
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				sm->xxkey_len = PMK_LEN;
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				os_memset(buf, 0, sizeof(buf));
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res == 0) {
19761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			struct rsn_pmksa_cache_entry *sa = NULL;
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump_key(MSG_DEBUG, "WPA: PMK from EAPOL state "
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"machines", sm->pmk, pmk_len);
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->pmk_len = pmk_len;
201c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt			if (sm->proto == WPA_PROTO_RSN &&
202c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt			    !wpa_key_mgmt_ft(sm->key_mgmt)) {
20361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				sa = pmksa_cache_add(sm->pmksa,
20461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt						     sm->pmk, pmk_len,
20561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt						     src_addr, sm->own_addr,
20661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt						     sm->network_ctx,
20761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt						     sm->key_mgmt);
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (!sm->cur_pmksa && pmkid &&
210c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			    pmksa_cache_get(sm->pmksa, src_addr, pmkid, NULL))
211c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			{
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"RSN: the new PMK matches with the "
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"PMKID");
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				abort_cached = 0;
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
21761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
21861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			if (!sm->cur_pmksa)
21961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				sm->cur_pmksa = sa;
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Failed to get master session key from "
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"EAPOL state machines - key handshake "
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"aborted");
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (sm->cur_pmksa) {
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"RSN: Cancelled PMKSA caching "
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"attempt");
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				sm->cur_pmksa = NULL;
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				abort_cached = 1;
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			} else if (!abort_cached) {
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return -1;
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
237c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	if (abort_cached && wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt) &&
238f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	    !wpa_key_mgmt_ft(sm->key_mgmt) && sm->key_mgmt != WPA_KEY_MGMT_OSEN)
239f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	{
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Send EAPOL-Start to trigger full EAP authentication. */
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		u8 *buf;
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		size_t buflen;
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"RSN: no PMKSA entry found - trigger "
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"full EAP authentication");
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		buf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_START,
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 NULL, 0, &buflen, NULL);
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (buf) {
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_sm_ether_send(sm, sm->bssid, ETH_P_EAPOL,
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  buf, buflen);
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(buf);
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -2;
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_supplicant_send_2_of_4 - Send message 2 of WPA/RSN 4-Way Handshake
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @dst: Destination address for the frame
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @key: Pointer to the EAPOL-Key frame header
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ver: Version bits from EAPOL-Key Key Info
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @nonce: Nonce value for the EAPOL-Key frame
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_ie: WPA/RSN IE
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_ie_len: Length of the WPA/RSN IE
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ptk: PTK to use for keyed hash and encryption
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       const struct wpa_eapol_key *key,
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       int ver, const u8 *nonce,
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       const u8 *wpa_ie, size_t wpa_ie_len,
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       struct wpa_ptk *ptk)
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t rlen;
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_eapol_key *reply;
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *rbuf;
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *rsn_ie_buf = NULL;
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_ie == NULL) {
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: No wpa_ie set - "
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"cannot generate msg 2/4");
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_key_mgmt_ft(sm->key_mgmt)) {
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int res;
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Add PMKR1Name into RSN IE (PMKID-List) and add MDIE and
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * FTIE from (Re)Association Response.
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		rsn_ie_buf = os_malloc(wpa_ie_len + 2 + 2 + PMKID_LEN +
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       sm->assoc_resp_ies_len);
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (rsn_ie_buf == NULL)
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(rsn_ie_buf, wpa_ie, wpa_ie_len);
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = wpa_insert_pmkid(rsn_ie_buf, wpa_ie_len,
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       sm->pmk_r1_name);
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res < 0) {
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(rsn_ie_buf);
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_ie_len += res;
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->assoc_resp_ies) {
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(rsn_ie_buf + wpa_ie_len, sm->assoc_resp_ies,
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  sm->assoc_resp_ies_len);
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_ie_len += sm->assoc_resp_ies_len;
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_ie = rsn_ie_buf;
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "WPA: WPA IE for msg 2/4", wpa_ie, wpa_ie_len);
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY,
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  NULL, sizeof(*reply) + wpa_ie_len,
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  &rlen, (void *) &reply);
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (rbuf == NULL) {
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(rsn_ie_buf);
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
333f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	reply->type = (sm->proto == WPA_PROTO_RSN ||
334f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		       sm->proto == WPA_PROTO_OSEN) ?
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE16(reply->key_info,
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_MIC);
338f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN)
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		WPA_PUT_BE16(reply->key_length, 0);
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(reply->key_length, key->key_length, 2);
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(reply->replay_counter, key->replay_counter,
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  WPA_REPLAY_COUNTER_LEN);
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "WPA: Replay Counter", reply->replay_counter,
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    WPA_REPLAY_COUNTER_LEN);
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE16(reply->key_data_length, wpa_ie_len);
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(reply + 1, wpa_ie, wpa_ie_len);
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(rsn_ie_buf);
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(reply->key_nonce, nonce, WPA_NONCE_LEN);
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 2/4");
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_eapol_key_send(sm, ptk->kck, ver, dst, ETH_P_EAPOL,
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   rbuf, rlen, reply->key_mic);
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr,
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  const struct wpa_eapol_key *key,
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  struct wpa_ptk *ptk)
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3659866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt	size_t ptk_len = wpa_cipher_key_len(sm->pairwise_cipher) + 32;
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_key_mgmt_ft(sm->key_mgmt))
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return wpa_derive_ptk_ft(sm, src_addr, key, ptk, ptk_len);
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_pmk_to_ptk(sm->pmk, sm->pmk_len, "Pairwise key expansion",
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       sm->own_addr, sm->bssid, sm->snonce, key->key_nonce,
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       (u8 *) ptk, ptk_len,
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       wpa_key_mgmt_sha256(sm->key_mgmt));
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_process_1_of_4(struct wpa_sm *sm,
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  const unsigned char *src_addr,
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  const struct wpa_eapol_key *key,
38243cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt					  u16 ver, const u8 *key_data,
38343cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt					  size_t key_data_len)
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_eapol_ie_parse ie;
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ptk *ptk;
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
388cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	u8 *kde, *kde_buf = NULL;
389cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	size_t kde_len;
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_sm_get_network_ctx(sm) == NULL) {
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: No SSID info "
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"found (msg 1 of 4)");
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE);
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: RX message 1 of 4-Way "
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"Handshake from " MACSTR " (ver=%d)", MAC2STR(src_addr), ver);
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&ie, 0, sizeof(ie));
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
403f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) {
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* RSN: msg 1/4 should contain PMKID for the selected PMK */
40543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		wpa_hexdump(MSG_DEBUG, "RSN: msg 1/4 key data",
40643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt			    key_data, key_data_len);
40743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0)
4081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			goto failed;
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ie.pmkid) {
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump(MSG_DEBUG, "RSN: PMKID from "
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    "Authenticator", ie.pmkid, PMKID_LEN);
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = wpa_supplicant_get_pmk(sm, src_addr, ie.pmkid);
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res == -2) {
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: Do not reply to "
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"msg 1/4 - requesting full EAP authentication");
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res)
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->renew_snonce) {
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (random_get_bytes(sm->snonce, WPA_NONCE_LEN)) {
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Failed to get random data for SNonce");
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto failed;
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->renew_snonce = 0;
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "WPA: Renewed SNonce",
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    sm->snonce, WPA_NONCE_LEN);
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Calculate PTK which will be stored as a temporary PTK until it has
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * been verified when processing message 3/4. */
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ptk = &sm->tptk;
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_derive_ptk(sm, src_addr, key, ptk);
4399866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt	if (sm->pairwise_cipher == WPA_CIPHER_TKIP) {
44061593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		u8 buf[8];
4419866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt		/* Supplicant: swap tx/rx Mic keys */
4429866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt		os_memcpy(buf, ptk->u.auth.tx_mic_key, 8);
4439866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt		os_memcpy(ptk->u.auth.tx_mic_key, ptk->u.auth.rx_mic_key, 8);
4449866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt		os_memcpy(ptk->u.auth.rx_mic_key, buf, 8);
44561593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		os_memset(buf, 0, sizeof(buf));
4469866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt	}
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->tptk_set = 1;
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
449cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	kde = sm->assoc_wpa_ie;
450cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	kde_len = sm->assoc_wpa_ie_len;
451cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
452cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#ifdef CONFIG_P2P
453cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (sm->p2p) {
454cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		kde_buf = os_malloc(kde_len + 2 + RSN_SELECTOR_LEN + 1);
455cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		if (kde_buf) {
456cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			u8 *pos;
457cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Add IP Address Request KDE "
458cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt				   "into EAPOL-Key 2/4");
459cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			os_memcpy(kde_buf, kde, kde_len);
460cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			kde = kde_buf;
461cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			pos = kde + kde_len;
462cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			*pos++ = WLAN_EID_VENDOR_SPECIFIC;
463cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			*pos++ = RSN_SELECTOR_LEN + 1;
464cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			RSN_SELECTOR_PUT(pos, WFA_KEY_DATA_IP_ADDR_REQ);
465cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			pos += RSN_SELECTOR_LEN;
466cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			*pos++ = 0x01;
467cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			kde_len = pos - kde;
468cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		}
469cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	}
470cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#endif /* CONFIG_P2P */
471cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_supplicant_send_2_of_4(sm, sm->bssid, key, ver, sm->snonce,
473cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt				       kde, kde_len, ptk))
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
476cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	os_free(kde_buf);
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(sm->anonce, key->key_nonce, WPA_NONCE_LEN);
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return;
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfailed:
481cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	os_free(kde_buf);
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_sm_start_preauth(void *eloop_ctx, void *timeout_ctx)
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_sm *sm = eloop_ctx;
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rsn_preauth_candidate_process(sm);
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_key_neg_complete(struct wpa_sm *sm,
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    const u8 *addr, int secure)
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"WPA: Key negotiation completed with "
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MACSTR " [PTK=%s GTK=%s]", MAC2STR(addr),
4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_cipher_txt(sm->pairwise_cipher),
5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_cipher_txt(sm->group_cipher));
5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_sm_cancel_auth_timeout(sm);
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_sm_set_state(sm, WPA_COMPLETED);
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (secure) {
5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_sm_mlme_setprotection(
5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm, addr, MLME_SETPROTECTION_PROTECT_TYPE_RX_TX,
5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eapol_sm_notify_portValid(sm->eapol, TRUE);
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_key_mgmt_wpa_psk(sm->key_mgmt))
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eapol_sm_notify_eap_success(sm->eapol, TRUE);
5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Start preauthentication after a short wait to avoid a
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * possible race condition between the data receive and key
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * configuration after the 4-Way Handshake. This increases the
5151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * likelihood of the first preauth EAPOL-Start frame getting to
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * the target AP.
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(1, 0, wpa_sm_start_preauth, sm, NULL);
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->cur_pmksa && sm->cur_pmksa->opportunistic) {
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"RSN: Authenticator accepted "
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"opportunistic PMKSA entry - marking it valid");
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->cur_pmksa->opportunistic = 0;
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_key_mgmt_ft(sm->key_mgmt)) {
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Prepare for the next transition */
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_ft_prepare_auth_request(sm, NULL);
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_sm_rekey_ptk(void *eloop_ctx, void *timeout_ctx)
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_sm *sm = eloop_ctx;
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Request PTK rekeying");
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_sm_key_request(sm, 0, 1);
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_install_ptk(struct wpa_sm *sm,
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const struct wpa_eapol_key *key)
5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int keylen, rsclen;
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum wpa_alg alg;
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *key_rsc;
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 null_rsc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"WPA: Installing PTK to the driver");
5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (sm->pairwise_cipher == WPA_CIPHER_NONE) {
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Pairwise Cipher "
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Suite: NONE - do not use pairwise keys");
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
5604530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
5614530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
5624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (!wpa_cipher_valid_pairwise(sm->pairwise_cipher)) {
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: Unsupported pairwise cipher %d",
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->pairwise_cipher);
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5694530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	alg = wpa_cipher_to_alg(sm->pairwise_cipher);
5704530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	keylen = wpa_cipher_key_len(sm->pairwise_cipher);
5714530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	rsclen = wpa_cipher_rsc_len(sm->pairwise_cipher);
5724530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
573f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) {
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_rsc = null_rsc;
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_rsc = key->key_rsc;
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "WPA: RSC", key_rsc, rsclen);
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_sm_set_key(sm, alg, sm->bssid, 0, 1, key_rsc, rsclen,
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (u8 *) sm->ptk.tk1, keylen) < 0) {
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: Failed to set PTK to the "
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"driver (alg=%d keylen=%d bssid=" MACSTR ")",
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			alg, keylen, MAC2STR(sm->bssid));
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->wpa_ptk_rekey) {
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL);
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(sm->wpa_ptk_rekey, 0, wpa_sm_rekey_ptk,
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       sm, NULL);
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_check_group_cipher(struct wpa_sm *sm,
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     int group_cipher,
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     int keylen, int maxkeylen,
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     int *key_rsc_len,
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     enum wpa_alg *alg)
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6054530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	int klen;
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6074530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	*alg = wpa_cipher_to_alg(group_cipher);
6084530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (*alg == WPA_ALG_NONE) {
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: Unsupported Group Cipher %d",
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			group_cipher);
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6144530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	*key_rsc_len = wpa_cipher_rsc_len(group_cipher);
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6164530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	klen = wpa_cipher_key_len(group_cipher);
6174530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (keylen != klen || maxkeylen < klen) {
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: Unsupported %s Group Cipher key length %d (%d)",
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_cipher_txt(group_cipher), keylen, maxkeylen);
6214530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return -1;
6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6234530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	return 0;
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_gtk_data {
6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum wpa_alg alg;
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int tx, key_rsc_len, keyidx;
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 gtk[32];
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int gtk_len;
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_install_gtk(struct wpa_sm *sm,
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const struct wpa_gtk_data *gd,
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const u8 *key_rsc)
6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *_gtk = gd->gtk;
6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 gtk_buf[32];
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_key(MSG_DEBUG, "WPA: Group Key", gd->gtk, gd->gtk_len);
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"WPA: Installing GTK to the driver (keyidx=%d tx=%d len=%d)",
6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		gd->keyidx, gd->tx, gd->gtk_len);
6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "WPA: RSC", key_rsc, gd->key_rsc_len);
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->group_cipher == WPA_CIPHER_TKIP) {
6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Swap Tx/Rx keys for Michael MIC */
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(gtk_buf, gd->gtk, 16);
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(gtk_buf + 16, gd->gtk + 24, 8);
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(gtk_buf + 24, gd->gtk + 16, 8);
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		_gtk = gtk_buf;
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->pairwise_cipher == WPA_CIPHER_NONE) {
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_sm_set_key(sm, gd->alg, NULL,
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   gd->keyidx, 1, key_rsc, gd->key_rsc_len,
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   _gtk, gd->gtk_len) < 0) {
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Failed to set GTK to the driver "
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"(Group only)");
66161593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt			os_memset(gtk_buf, 0, sizeof(gtk_buf));
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (wpa_sm_set_key(sm, gd->alg, broadcast_ether_addr,
6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  gd->keyidx, gd->tx, key_rsc, gd->key_rsc_len,
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  _gtk, gd->gtk_len) < 0) {
6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: Failed to set GTK to "
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"the driver (alg=%d keylen=%d keyidx=%d)",
6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			gd->alg, gd->gtk_len, gd->keyidx);
67161593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		os_memset(gtk_buf, 0, sizeof(gtk_buf));
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
67461593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt	os_memset(gtk_buf, 0, sizeof(gtk_buf));
6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_gtk_tx_bit_workaround(const struct wpa_sm *sm,
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						int tx)
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tx && sm->pairwise_cipher != WPA_CIPHER_NONE) {
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Ignore Tx bit for GTK if a pairwise key is used. One AP
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * seemed to set this bit (incorrectly, since Tx is only when
6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * doing Group Key only APs) and without this workaround, the
6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * data connection does not work because wpa_supplicant
6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * configured non-zero keyidx to be used for unicast. */
6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: Tx bit set for GTK, but pairwise "
6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"keys are used - ignore Tx bit");
6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return tx;
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_pairwise_gtk(struct wpa_sm *sm,
6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       const struct wpa_eapol_key *key,
7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       const u8 *gtk, size_t gtk_len,
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       int key_info)
7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_gtk_data gd;
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * IEEE Std 802.11i-2004 - 8.5.2 EAPOL-Key frames - Figure 43x
7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * GTK KDE format:
7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * KeyID[bits 0-1], Tx [bit 2], Reserved [bits 3-7]
7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Reserved [bits 0-7]
7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * GTK
7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&gd, 0, sizeof(gd));
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_key(MSG_DEBUG, "RSN: received GTK in pairwise handshake",
7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			gtk, gtk_len);
7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (gtk_len < 2 || gtk_len - 2 > sizeof(gd.gtk))
7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gd.keyidx = gtk[0] & 0x3;
7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gd.tx = wpa_supplicant_gtk_tx_bit_workaround(sm,
7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						     !!(gtk[0] & BIT(2)));
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gtk += 2;
7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gtk_len -= 2;
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(gd.gtk, gtk, gtk_len);
7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gd.gtk_len = gtk_len;
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
729fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	if (sm->group_cipher != WPA_CIPHER_GTK_NOT_USED &&
730fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	    (wpa_supplicant_check_group_cipher(sm, sm->group_cipher,
731fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt					       gtk_len, gtk_len,
732fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt					       &gd.key_rsc_len, &gd.alg) ||
733fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	     wpa_supplicant_install_gtk(sm, &gd, key->key_rsc))) {
7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"RSN: Failed to install GTK");
73661593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		os_memset(&gd, 0, sizeof(gd));
7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
73961593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt	os_memset(&gd, 0, sizeof(gd));
7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_key_neg_complete(sm, sm->bssid,
7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					key_info & WPA_KEY_INFO_SECURE);
7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ieee80211w_set_keys(struct wpa_sm *sm,
7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       struct wpa_eapol_ie_parse *ie)
7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W
751b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	if (!wpa_cipher_valid_mgmt_group(sm->mgmt_group_cipher))
7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie->igtk) {
755b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt		size_t len;
7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		const struct wpa_igtk_kde *igtk;
7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		u16 keyidx;
758b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt		len = wpa_cipher_key_len(sm->mgmt_group_cipher);
759b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt		if (ie->igtk_len != WPA_IGTK_KDE_PREFIX_LEN + len)
7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		igtk = (const struct wpa_igtk_kde *) ie->igtk;
7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		keyidx = WPA_GET_LE16(igtk->keyid);
7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: IGTK keyid %d "
7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"pn %02x%02x%02x%02x%02x%02x",
7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			keyidx, MAC2STR(igtk->pn));
7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump_key(MSG_DEBUG, "WPA: IGTK",
767b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt				igtk->igtk, len);
7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (keyidx > 4095) {
7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Invalid IGTK KeyID %d", keyidx);
7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
773b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt		if (wpa_sm_set_key(sm, wpa_cipher_to_alg(sm->mgmt_group_cipher),
774b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt				   broadcast_ether_addr,
7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   keyidx, 0, igtk->pn, sizeof(igtk->pn),
776b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt				   igtk->igtk, len) < 0) {
7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Failed to configure IGTK to the driver");
7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_IEEE80211W */
7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */
7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_report_ie_mismatch(struct wpa_sm *sm,
7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   const char *reason, const u8 *src_addr,
7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   const u8 *wpa_ie, size_t wpa_ie_len,
7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   const u8 *rsn_ie, size_t rsn_ie_len)
7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: %s (src=" MACSTR ")",
7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		reason, MAC2STR(src_addr));
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->ap_wpa_ie) {
7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_INFO, "WPA: WPA IE in Beacon/ProbeResp",
8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    sm->ap_wpa_ie, sm->ap_wpa_ie_len);
8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_ie) {
8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!sm->ap_wpa_ie) {
8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: No WPA IE in Beacon/ProbeResp");
8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_INFO, "WPA: WPA IE in 3/4 msg",
8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    wpa_ie, wpa_ie_len);
8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->ap_rsn_ie) {
8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_INFO, "WPA: RSN IE in Beacon/ProbeResp",
8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    sm->ap_rsn_ie, sm->ap_rsn_ie_len);
8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (rsn_ie) {
8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!sm->ap_rsn_ie) {
8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: No RSN IE in Beacon/ProbeResp");
8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_INFO, "WPA: RSN IE in 3/4 msg",
8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    rsn_ie, rsn_ie_len);
8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
824d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	wpa_sm_deauthenticate(sm, WLAN_REASON_IE_IN_4WAY_DIFFERS);
8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ft_validate_mdie(struct wpa_sm *sm,
8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    const unsigned char *src_addr,
8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    struct wpa_eapol_ie_parse *ie,
8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    const u8 *assoc_resp_mdie)
8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct rsn_mdie *mdie;
8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	mdie = (struct rsn_mdie *) (ie->mdie + 2);
8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie->mdie == NULL || ie->mdie_len < 2 + sizeof(*mdie) ||
8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(mdie->mobility_domain, sm->mobility_domain,
8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      MOBILITY_DOMAIN_ID_LEN) != 0) {
8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: MDIE in msg 3/4 did "
8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"not match with the current mobility domain");
8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (assoc_resp_mdie &&
8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (assoc_resp_mdie[1] != ie->mdie[1] ||
8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     os_memcmp(assoc_resp_mdie, ie->mdie, 2 + ie->mdie[1]) != 0)) {
8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: MDIE mismatch");
8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "FT: MDIE in EAPOL-Key msg 3/4",
8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    ie->mdie, 2 + ie->mdie[1]);
8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "FT: MDIE in (Re)Association Response",
8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    assoc_resp_mdie, 2 + assoc_resp_mdie[1]);
8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ft_validate_ftie(struct wpa_sm *sm,
8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    const unsigned char *src_addr,
8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    struct wpa_eapol_ie_parse *ie,
8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    const u8 *assoc_resp_ftie)
8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie->ftie == NULL) {
8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"FT: No FTIE in EAPOL-Key msg 3/4");
8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (assoc_resp_ftie == NULL)
8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (assoc_resp_ftie[1] != ie->ftie[1] ||
8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(assoc_resp_ftie, ie->ftie, 2 + ie->ftie[1]) != 0) {
8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: FTIE mismatch");
8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "FT: FTIE in EAPOL-Key msg 3/4",
8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    ie->ftie, 2 + ie->ftie[1]);
8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "FT: FTIE in (Re)Association Response",
8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    assoc_resp_ftie, 2 + assoc_resp_ftie[1]);
8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ft_validate_rsnie(struct wpa_sm *sm,
8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     const unsigned char *src_addr,
8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     struct wpa_eapol_ie_parse *ie)
8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ie_data rsn;
8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!ie->rsn_ie)
8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Verify that PMKR1Name from EAPOL-Key message 3/4
9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * matches with the value we derived.
9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_parse_wpa_ie_rsn(ie->rsn_ie, ie->rsn_ie_len, &rsn) < 0 ||
9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    rsn.num_pmkid != 1 || rsn.pmkid == NULL) {
9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: No PMKR1Name in "
9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"FT 4-way handshake message 3/4");
9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
909c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt	if (os_memcmp_const(rsn.pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN) != 0)
910c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt	{
9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"FT: PMKR1Name mismatch in "
9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"FT 4-way handshake message 3/4");
9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from Authenticator",
9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    rsn.pmkid, WPA_PMK_NAME_LEN);
9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "FT: Derived PMKR1Name",
9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    sm->pmk_r1_name, WPA_PMK_NAME_LEN);
9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_validate_ie_ft(struct wpa_sm *sm,
9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 const unsigned char *src_addr,
9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 struct wpa_eapol_ie_parse *ie)
9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos, *end, *mdie = NULL, *ftie = NULL;
9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->assoc_resp_ies) {
9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = sm->assoc_resp_ies;
9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		end = pos + sm->assoc_resp_ies_len;
9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (pos + 2 < end) {
9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (pos + 2 + pos[1] > end)
9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			switch (*pos) {
9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			case WLAN_EID_MOBILITY_DOMAIN:
9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				mdie = pos;
9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			case WLAN_EID_FAST_BSS_TRANSITION:
9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				ftie = pos;
9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos += 2 + pos[1];
9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ft_validate_mdie(sm, src_addr, ie, mdie) < 0 ||
9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ft_validate_ftie(sm, src_addr, ie, ftie) < 0 ||
9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ft_validate_rsnie(sm, src_addr, ie) < 0)
9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_validate_ie(struct wpa_sm *sm,
9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const unsigned char *src_addr,
9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      struct wpa_eapol_ie_parse *ie)
9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->ap_wpa_ie == NULL && sm->ap_rsn_ie == NULL) {
9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: No WPA/RSN IE for this AP known. "
9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Trying to get from scan results");
9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_sm_get_beacon_ie(sm) < 0) {
9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Could not find AP from "
9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"the scan results");
9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG,
9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Found the current AP from "
9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"updated scan results");
9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie->wpa_ie == NULL && ie->rsn_ie == NULL &&
9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (sm->ap_wpa_ie || sm->ap_rsn_ie)) {
9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_report_ie_mismatch(sm, "IE in 3/4 msg does not match "
9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       "with IE in Beacon/ProbeResp (no IE?)",
9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       src_addr, ie->wpa_ie, ie->wpa_ie_len,
9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       ie->rsn_ie, ie->rsn_ie_len);
9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((ie->wpa_ie && sm->ap_wpa_ie &&
9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     (ie->wpa_ie_len != sm->ap_wpa_ie_len ||
9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	      os_memcmp(ie->wpa_ie, sm->ap_wpa_ie, ie->wpa_ie_len) != 0)) ||
9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (ie->rsn_ie && sm->ap_rsn_ie &&
9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     wpa_compare_rsn_ie(wpa_key_mgmt_ft(sm->key_mgmt),
9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				sm->ap_rsn_ie, sm->ap_rsn_ie_len,
9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				ie->rsn_ie, ie->rsn_ie_len))) {
9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_report_ie_mismatch(sm, "IE in 3/4 msg does not match "
9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       "with IE in Beacon/ProbeResp",
9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       src_addr, ie->wpa_ie, ie->wpa_ie_len,
9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       ie->rsn_ie, ie->rsn_ie_len);
9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->proto == WPA_PROTO_WPA &&
10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ie->rsn_ie && sm->ap_rsn_ie == NULL && sm->rsn_enabled) {
10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_report_ie_mismatch(sm, "Possible downgrade attack "
10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       "detected - RSN was enabled and RSN IE "
10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       "was in msg 3/4, but not in "
10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       "Beacon/ProbeResp",
10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       src_addr, ie->wpa_ie, ie->wpa_ie_len,
10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       ie->rsn_ie, ie->rsn_ie_len);
10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_key_mgmt_ft(sm->key_mgmt) &&
10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wpa_supplicant_validate_ie_ft(sm, src_addr, ie) < 0)
10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_supplicant_send_4_of_4 - Send message 4 of WPA/RSN 4-Way Handshake
10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @dst: Destination address for the frame
10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @key: Pointer to the EAPOL-Key frame header
10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ver: Version bits from EAPOL-Key Key Info
10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @key_info: Key Info
10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ptk: PTK to use for keyed hash and encryption
10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst,
10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       const struct wpa_eapol_key *key,
10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       u16 ver, u16 key_info,
10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       struct wpa_ptk *ptk)
10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t rlen;
10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_eapol_key *reply;
10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *rbuf;
10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
104321de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt				  sizeof(*reply), &rlen, (void *) &reply);
10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (rbuf == NULL)
10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1047f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	reply->type = (sm->proto == WPA_PROTO_RSN ||
1048f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		       sm->proto == WPA_PROTO_OSEN) ?
10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key_info &= WPA_KEY_INFO_SECURE;
10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key_info |= ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_MIC;
10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE16(reply->key_info, key_info);
1053f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN)
10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		WPA_PUT_BE16(reply->key_length, 0);
10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(reply->key_length, key->key_length, 2);
10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(reply->replay_counter, key->replay_counter,
10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  WPA_REPLAY_COUNTER_LEN);
10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
106021de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt	WPA_PUT_BE16(reply->key_data_length, 0);
10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 4/4");
10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_eapol_key_send(sm, ptk->kck, ver, dst, ETH_P_EAPOL,
10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   rbuf, rlen, reply->key_mic);
10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_process_3_of_4(struct wpa_sm *sm,
10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  const struct wpa_eapol_key *key,
107243cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt					  u16 ver, const u8 *key_data,
107343cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt					  size_t key_data_len)
10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
107543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	u16 key_info, keylen;
10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_eapol_ie_parse ie;
10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE);
10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: RX message 3 of 4-Way "
10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"Handshake from " MACSTR " (ver=%d)", MAC2STR(sm->bssid), ver);
10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key_info = WPA_GET_BE16(key->key_info);
10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
108443cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	wpa_hexdump(MSG_DEBUG, "WPA: IE KeyData", key_data, key_data_len);
108543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0)
10861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		goto failed;
10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: GTK IE in unencrypted key data");
10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W
10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie.igtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: IGTK KDE in unencrypted key data");
10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1099b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	if (ie.igtk &&
1100b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	    wpa_cipher_valid_mgmt_group(sm->mgmt_group_cipher) &&
1101b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	    ie.igtk_len != WPA_IGTK_KDE_PREFIX_LEN +
1102b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	    (unsigned int) wpa_cipher_key_len(sm->mgmt_group_cipher)) {
11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: Invalid IGTK KDE length %lu",
11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			(unsigned long) ie.igtk_len);
11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */
11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_supplicant_validate_ie(sm, sm->bssid, &ie) < 0)
11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(sm->anonce, key->key_nonce, WPA_NONCE_LEN) != 0) {
11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: ANonce from message 1 of 4-Way Handshake "
11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"differs from 3 of 4-Way Handshake - drop packet (src="
11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MACSTR ")", MAC2STR(sm->bssid));
11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	keylen = WPA_GET_BE16(key->key_length);
11224530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (keylen != wpa_cipher_key_len(sm->pairwise_cipher)) {
11234530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
11244530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			"WPA: Invalid %s key length %d (src=" MACSTR
11254530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			")", wpa_cipher_txt(sm->pairwise_cipher), keylen,
11264530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			MAC2STR(sm->bssid));
11274530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		goto failed;
11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1130cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#ifdef CONFIG_P2P
1131cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (ie.ip_addr_alloc) {
1132cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		os_memcpy(sm->p2p_ip_addr, ie.ip_addr_alloc, 3 * 4);
1133cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		wpa_hexdump(MSG_DEBUG, "P2P: IP address info",
1134cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			    sm->p2p_ip_addr, sizeof(sm->p2p_ip_addr));
1135cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	}
1136cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#endif /* CONFIG_P2P */
1137cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_supplicant_send_4_of_4(sm, sm->bssid, key, ver, key_info,
113921de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt				       &sm->ptk)) {
11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* SNonce was successfully used in msg 3/4, so mark it to be renewed
11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * for the next 4-Way Handshake. If msg 3 is received again, the old
11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * SNonce will still be used to avoid changing PTK. */
11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->renew_snonce = 1;
11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (key_info & WPA_KEY_INFO_INSTALL) {
11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_supplicant_install_ptk(sm, key))
11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto failed;
11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (key_info & WPA_KEY_INFO_SECURE) {
11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_sm_mlme_setprotection(
11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm, sm->bssid, MLME_SETPROTECTION_PROTECT_TYPE_RX,
11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eapol_sm_notify_portValid(sm->eapol, TRUE);
11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE);
11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1161fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	if (sm->group_cipher == WPA_CIPHER_GTK_NOT_USED) {
1162fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		wpa_supplicant_key_neg_complete(sm, sm->bssid,
1163fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt						key_info & WPA_KEY_INFO_SECURE);
1164fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	} else if (ie.gtk &&
11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wpa_supplicant_pairwise_gtk(sm, key,
11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					ie.gtk, ie.gtk_len, key_info) < 0) {
11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"RSN: Failed to configure GTK");
11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ieee80211w_set_keys(sm, &ie) < 0) {
11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"RSN: Failed to configure IGTK");
11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1178cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	if (ie.gtk)
1179cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		wpa_sm_set_rekey_offload(sm);
11801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return;
11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfailed:
11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_process_1_of_2_rsn(struct wpa_sm *sm,
11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     const u8 *keydata,
11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     size_t keydatalen,
11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     u16 key_info,
11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     struct wpa_gtk_data *gd)
11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int maxkeylen;
11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_eapol_ie_parse ie;
11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "RSN: msg 1/2 key data", keydata, keydatalen);
11981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (wpa_supplicant_parse_ies(keydata, keydatalen, &ie) < 0)
11991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return -1;
12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: GTK IE in unencrypted key data");
12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie.gtk == NULL) {
12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: No GTK IE in Group Key msg 1/2");
12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	maxkeylen = gd->gtk_len = ie.gtk_len - 2;
12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_supplicant_check_group_cipher(sm, sm->group_cipher,
12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      gd->gtk_len, maxkeylen,
12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      &gd->key_rsc_len, &gd->alg))
12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "RSN: received GTK in group key handshake",
12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    ie.gtk, ie.gtk_len);
12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gd->keyidx = ie.gtk[0] & 0x3;
12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gd->tx = wpa_supplicant_gtk_tx_bit_workaround(sm,
12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						      !!(ie.gtk[0] & BIT(2)));
12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie.gtk_len - 2 > sizeof(gd->gtk)) {
12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"RSN: Too long GTK in GTK IE (len=%lu)",
12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			(unsigned long) ie.gtk_len - 2);
12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(gd->gtk, ie.gtk + 2, ie.gtk_len - 2);
12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ieee80211w_set_keys(sm, &ie) < 0)
12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"RSN: Failed to configure IGTK");
12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_process_1_of_2_wpa(struct wpa_sm *sm,
12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     const struct wpa_eapol_key *key,
124043cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt					     const u8 *key_data,
124143cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt					     size_t key_data_len, u16 key_info,
124243cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt					     u16 ver, struct wpa_gtk_data *gd)
12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t maxkeylen;
12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gd->gtk_len = WPA_GET_BE16(key->key_length);
124743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	maxkeylen = key_data_len;
12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (maxkeylen < 8) {
12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Too short maxkeylen (%lu)",
12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				(unsigned long) maxkeylen);
12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		maxkeylen -= 8;
12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_supplicant_check_group_cipher(sm, sm->group_cipher,
12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      gd->gtk_len, maxkeylen,
12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      &gd->key_rsc_len, &gd->alg))
12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gd->keyidx = (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >>
12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		WPA_KEY_INFO_KEY_INDEX_SHIFT;
12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4) {
126661593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		u8 ek[32];
126743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		if (key_data_len > sizeof(gd->gtk)) {
12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: RC4 key data too long (%lu)",
127043cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt				(unsigned long) key_data_len);
12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
127361593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		os_memcpy(ek, key->key_iv, 16);
127461593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		os_memcpy(ek + 16, sm->ptk.kek, 16);
127543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		os_memcpy(gd->gtk, key_data, key_data_len);
127643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		if (rc4_skip(ek, 32, 256, gd->gtk, key_data_len)) {
127761593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt			os_memset(ek, 0, sizeof(ek));
12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: RC4 failed");
12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
128261593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		os_memset(ek, 0, sizeof(ek));
12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
128443cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		if (maxkeylen % 8) {
12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Unsupported AES-WRAP len %lu",
128743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt				(unsigned long) maxkeylen);
12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (maxkeylen > sizeof(gd->gtk)) {
12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: AES-WRAP key data "
12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"too long (keydatalen=%lu maxkeylen=%lu)",
129443cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt				(unsigned long) key_data_len,
12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				(unsigned long) maxkeylen);
12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
12989ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt		if (aes_unwrap(sm->ptk.kek, 16, maxkeylen / 8, key_data,
12999ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt			       gd->gtk)) {
13008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: AES unwrap failed - could not decrypt "
13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"GTK");
13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: Unsupported key_info type %d", ver);
13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gd->tx = wpa_supplicant_gtk_tx_bit_workaround(
13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm, !!(key_info & WPA_KEY_INFO_TXRX));
13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_send_2_of_2(struct wpa_sm *sm,
13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const struct wpa_eapol_key *key,
13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      int ver, u16 key_info)
13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t rlen;
13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_eapol_key *reply;
13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *rbuf;
13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  sizeof(*reply), &rlen, (void *) &reply);
13268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (rbuf == NULL)
13278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
13288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1329f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	reply->type = (sm->proto == WPA_PROTO_RSN ||
1330f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		       sm->proto == WPA_PROTO_OSEN) ?
13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
13328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key_info &= WPA_KEY_INFO_KEY_INDEX_MASK;
13338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key_info |= ver | WPA_KEY_INFO_MIC | WPA_KEY_INFO_SECURE;
13348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE16(reply->key_info, key_info);
1335f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN)
13368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		WPA_PUT_BE16(reply->key_length, 0);
13378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(reply->key_length, key->key_length, 2);
13398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(reply->replay_counter, key->replay_counter,
13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  WPA_REPLAY_COUNTER_LEN);
13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE16(reply->key_data_length, 0);
13438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 2/2");
13458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_eapol_key_send(sm, sm->ptk.kck, ver, sm->bssid, ETH_P_EAPOL,
13468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   rbuf, rlen, reply->key_mic);
13478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_process_1_of_2(struct wpa_sm *sm,
13538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  const unsigned char *src_addr,
13548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  const struct wpa_eapol_key *key,
135543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt					  const u8 *key_data,
135643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt					  size_t key_data_len, u16 ver)
13578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
135843cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	u16 key_info;
13598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int rekey, ret;
13608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_gtk_data gd;
13618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&gd, 0, sizeof(gd));
13638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rekey = wpa_sm_get_state(sm) == WPA_COMPLETED;
13658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: RX message 1 of Group Key "
13668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"Handshake from " MACSTR " (ver=%d)", MAC2STR(src_addr), ver);
13678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key_info = WPA_GET_BE16(key->key_info);
13698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1370f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) {
137143cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		ret = wpa_supplicant_process_1_of_2_rsn(sm, key_data,
137243cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt							key_data_len, key_info,
13738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							&gd);
13748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
137543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		ret = wpa_supplicant_process_1_of_2_wpa(sm, key, key_data,
137643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt							key_data_len,
137743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt							key_info, ver, &gd);
13788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE);
13818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret)
13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
13848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_supplicant_install_gtk(sm, &gd, key->key_rsc) ||
13868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wpa_supplicant_send_2_of_2(sm, key, ver, key_info))
13878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
13888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (rekey) {
13908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Group rekeying "
13918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"completed with " MACSTR " [GTK=%s]",
13928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(sm->bssid), wpa_cipher_txt(sm->group_cipher));
13938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_sm_cancel_auth_timeout(sm);
13948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_sm_set_state(sm, WPA_COMPLETED);
13958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
13968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_key_neg_complete(sm, sm->bssid,
13978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						key_info &
13988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						WPA_KEY_INFO_SECURE);
13998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1400cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt
1401cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	wpa_sm_set_rekey_offload(sm);
1402cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt
14038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return;
14048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfailed:
14068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
14078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
14088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_verify_eapol_key_mic(struct wpa_sm *sm,
14118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       struct wpa_eapol_key *key,
14128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       u16 ver,
14138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       const u8 *buf, size_t len)
14148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
14158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 mic[16];
14168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ok = 0;
14178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(mic, key->key_mic, 16);
14198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->tptk_set) {
14208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(key->key_mic, 0, 16);
14218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_eapol_key_mic(sm->tptk.kck, ver, buf, len,
14228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  key->key_mic);
1423c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt		if (os_memcmp_const(mic, key->key_mic, 16) != 0) {
14248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
14258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Invalid EAPOL-Key MIC "
14268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"when using TPTK - ignoring TPTK");
14278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
14288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ok = 1;
14298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->tptk_set = 0;
14308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->ptk_set = 1;
14318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(&sm->ptk, &sm->tptk, sizeof(sm->ptk));
143261593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt			os_memset(&sm->tptk, 0, sizeof(sm->tptk));
14338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
14348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!ok && sm->ptk_set) {
14378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(key->key_mic, 0, 16);
14388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_eapol_key_mic(sm->ptk.kck, ver, buf, len,
14398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  key->key_mic);
1440c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt		if (os_memcmp_const(mic, key->key_mic, 16) != 0) {
14418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
14428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Invalid EAPOL-Key MIC - "
14438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"dropping packet");
14448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
14458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
14468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ok = 1;
14478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!ok) {
14508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
14518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: Could not verify EAPOL-Key MIC - "
14528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"dropping packet");
14538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
14548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(sm->rx_replay_counter, key->replay_counter,
14578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  WPA_REPLAY_COUNTER_LEN);
14588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->rx_replay_counter_set = 1;
14598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
14608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
14618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Decrypt RSN EAPOL-Key key data (RC4 or AES-WRAP) */
14648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm,
146543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt					   struct wpa_eapol_key *key, u16 ver,
146643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt					   u8 *key_data, size_t *key_data_len)
14678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
14688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "RSN: encrypted key data",
146943cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		    key_data, *key_data_len);
14708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!sm->ptk_set) {
14718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
14728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: PTK not available, cannot decrypt EAPOL-Key Key "
14738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Data");
14748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
14758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Decrypt key data here so that this operation does not need
14788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * to be implemented separately for each message type. */
14798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4) {
14808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		u8 ek[32];
14818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(ek, key->key_iv, 16);
14828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(ek + 16, sm->ptk.kek, 16);
148343cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		if (rc4_skip(ek, 32, 256, key_data, *key_data_len)) {
148461593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt			os_memset(ek, 0, sizeof(ek));
14858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
14868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: RC4 failed");
14878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
14888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
148961593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		os_memset(ek, 0, sizeof(ek));
14908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
1491f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		   ver == WPA_KEY_INFO_TYPE_AES_128_CMAC ||
1492f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		   sm->key_mgmt == WPA_KEY_MGMT_OSEN) {
14938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		u8 *buf;
149443cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		if (*key_data_len < 8 || *key_data_len % 8) {
14958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
149643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt				"WPA: Unsupported AES-WRAP len %u",
149743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt				(unsigned int) *key_data_len);
14988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
14998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
150043cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		*key_data_len -= 8; /* AES-WRAP adds 8 bytes */
150143cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		buf = os_malloc(*key_data_len);
15028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (buf == NULL) {
15038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
15048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: No memory for AES-UNWRAP buffer");
15058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
15068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
15079ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt		if (aes_unwrap(sm->ptk.kek, 16, *key_data_len / 8,
150843cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt			       key_data, buf)) {
15098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(buf);
15108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
15118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: AES unwrap failed - "
15128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"could not decrypt EAPOL-Key key data");
15138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
15148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
151543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		os_memcpy(key_data, buf, *key_data_len);
15168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(buf);
151743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		WPA_PUT_BE16(key->key_data_length, *key_data_len);
15188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
15198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
15208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: Unsupported key_info type %d", ver);
15218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
15228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_key(MSG_DEBUG, "WPA: decrypted EAPOL-Key key data",
152443cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt			key_data, *key_data_len);
15258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
15268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
15308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_aborted_cached - Notify WPA that PMKSA caching was aborted
15318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
15328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
15338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_aborted_cached(struct wpa_sm *sm)
15348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm && sm->cur_pmksa) {
15368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
15378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"RSN: Cancelling PMKSA caching attempt");
15388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->cur_pmksa = NULL;
15398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_eapol_key_dump(struct wpa_sm *sm,
15448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       const struct wpa_eapol_key *key)
15458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_STDOUT_DEBUG
15478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u16 key_info = WPA_GET_BE16(key->key_info);
15488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "  EAPOL-Key type=%d", key->type);
15508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
15518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"  key_info 0x%x (ver=%d keyidx=%d rsvd=%d %s%s%s%s%s%s%s%s)",
15528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_info, key_info & WPA_KEY_INFO_TYPE_MASK,
15538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		(key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >>
15548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		WPA_KEY_INFO_KEY_INDEX_SHIFT,
15558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		(key_info & (BIT(13) | BIT(14) | BIT(15))) >> 13,
15568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_info & WPA_KEY_INFO_KEY_TYPE ? "Pairwise" : "Group",
15578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_info & WPA_KEY_INFO_INSTALL ? " Install" : "",
15588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_info & WPA_KEY_INFO_ACK ? " Ack" : "",
15598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_info & WPA_KEY_INFO_MIC ? " MIC" : "",
15608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_info & WPA_KEY_INFO_SECURE ? " Secure" : "",
15618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_info & WPA_KEY_INFO_ERROR ? " Error" : "",
15628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_info & WPA_KEY_INFO_REQUEST ? " Request" : "",
15638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_info & WPA_KEY_INFO_ENCR_KEY_DATA ? " Encr" : "");
15648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
15658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"  key_length=%u key_data_length=%u",
15668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		WPA_GET_BE16(key->key_length),
15678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		WPA_GET_BE16(key->key_data_length));
15688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "  replay_counter",
15698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    key->replay_counter, WPA_REPLAY_COUNTER_LEN);
15708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "  key_nonce", key->key_nonce, WPA_NONCE_LEN);
15718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "  key_iv", key->key_iv, 16);
15728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "  key_rsc", key->key_rsc, 8);
15738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "  key_id (reserved)", key->key_id, 8);
15748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "  key_mic", key->key_mic, 16);
15758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_STDOUT_DEBUG */
15768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
15808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_rx_eapol - Process received WPA EAPOL frames
15818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
15828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @src_addr: Source MAC address of the EAPOL packet
15838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Pointer to the beginning of the EAPOL data (EAPOL header)
15848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Length of the EAPOL frame
15858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 1 = WPA EAPOL-Key processed, 0 = not a WPA EAPOL-Key, -1 failure
15868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
15878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called for each received EAPOL frame. Other than EAPOL-Key
15888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * frames can be skipped if filtering is done elsewhere. wpa_sm_rx_eapol() is
15898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * only processing WPA and WPA2 EAPOL-Key frames.
15908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
15918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * The received EAPOL-Key packets are validated and valid packets are replied
15928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to. In addition, key material (PTK, GTK) is configured at the end of a
15938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * successful key handshake.
15948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
15958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
15968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    const u8 *buf, size_t len)
15978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
159843cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	size_t plen, data_len, key_data_len;
159943cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	const struct ieee802_1x_hdr *hdr;
16008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_eapol_key *key;
16018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u16 key_info, ver;
160243cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	u8 *tmp = NULL;
16038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret = -1;
16048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_peerkey *peerkey = NULL;
160543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	u8 *key_data;
16068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
16088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->ft_completed = 0;
16098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
16108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < sizeof(*hdr) + sizeof(*key)) {
16128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
16138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: EAPOL frame too short to be a WPA "
16148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"EAPOL-Key (len %lu, expecting at least %lu)",
16158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			(unsigned long) len,
16168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			(unsigned long) sizeof(*hdr) + sizeof(*key));
16178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
16188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
162043cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	hdr = (const struct ieee802_1x_hdr *) buf;
16218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	plen = be_to_host16(hdr->length);
16228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data_len = plen + sizeof(*hdr);
16238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
16248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"IEEE 802.1X RX: version=%d type=%d length=%lu",
16258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hdr->version, hdr->type, (unsigned long) plen);
16268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hdr->version < EAPOL_VERSION) {
16288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* TODO: backwards compatibility */
16298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hdr->type != IEEE802_1X_TYPE_EAPOL_KEY) {
16318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
16328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: EAPOL frame (type %u) discarded, "
16338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"not a Key frame", hdr->type);
16348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = 0;
16358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
16368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
163743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL-Key", buf, len);
16388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (plen > len - sizeof(*hdr) || plen < sizeof(*key)) {
16398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
16408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: EAPOL frame payload size %lu "
16418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"invalid (frame size %lu)",
16428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			(unsigned long) plen, (unsigned long) len);
16438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = 0;
16448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
16458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
164643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	if (data_len < len) {
164743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
164843cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt			"WPA: ignoring %lu bytes after the IEEE 802.1X data",
164943cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt			(unsigned long) len - data_len);
165043cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	}
165143cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt
165243cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	/*
165343cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	 * Make a copy of the frame since we need to modify the buffer during
165443cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	 * MAC validation and Key Data decryption.
165543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	 */
165643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	tmp = os_malloc(data_len);
165743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	if (tmp == NULL)
165843cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		goto out;
165943cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	os_memcpy(tmp, buf, data_len);
166043cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	key = (struct wpa_eapol_key *) (tmp + sizeof(struct ieee802_1x_hdr));
166143cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	key_data = (u8 *) (key + 1);
16628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (key->type != EAPOL_KEY_TYPE_WPA && key->type != EAPOL_KEY_TYPE_RSN)
16648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{
16658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
16668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: EAPOL-Key type (%d) unknown, discarded",
16678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			key->type);
16688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = 0;
16698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
16708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_eapol_key_dump(sm, key);
16728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
167343cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	key_data_len = WPA_GET_BE16(key->key_data_length);
167443cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	if (key_data_len > plen - sizeof(struct wpa_eapol_key)) {
167543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Invalid EAPOL-Key "
167643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt			"frame - key_data overflow (%u > %u)",
167743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt			(unsigned int) key_data_len,
167843cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt			(unsigned int) (plen - sizeof(struct wpa_eapol_key)));
167943cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		goto out;
16808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
168143cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt
168243cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	eapol_sm_notify_lower_layer_success(sm->eapol, 0);
16838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key_info = WPA_GET_BE16(key->key_info);
16848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ver = key_info & WPA_KEY_INFO_TYPE_MASK;
16858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ver != WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 &&
16868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W)
16878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ver != WPA_KEY_INFO_TYPE_AES_128_CMAC &&
16888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */
1689f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	    ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES &&
1690f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	    sm->key_mgmt != WPA_KEY_MGMT_OSEN) {
16918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
16928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: Unsupported EAPOL-Key descriptor version %d",
16938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ver);
16948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
16958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1697f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	if (sm->key_mgmt == WPA_KEY_MGMT_OSEN &&
1698f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	    ver != WPA_KEY_INFO_TYPE_AKM_DEFINED) {
1699f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
1700f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt			"OSEN: Unsupported EAPOL-Key descriptor version %d",
1701f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt			ver);
1702f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		goto out;
1703f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	}
1704f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt
17058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
17068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_key_mgmt_ft(sm->key_mgmt)) {
17078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* IEEE 802.11r uses a new key_info type (AES-128-CMAC). */
17088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) {
17098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
17108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"FT: AP did not use AES-128-CMAC");
17118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto out;
17128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
17138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
17148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
17158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W
17168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_key_mgmt_sha256(sm->key_mgmt)) {
1717f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC &&
1718f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		    sm->key_mgmt != WPA_KEY_MGMT_OSEN) {
17198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
17208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: AP did not use the "
17218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"negotiated AES-128-CMAC");
17228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto out;
17238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
17248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
17258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */
17268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->pairwise_cipher == WPA_CIPHER_CCMP &&
17278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
17288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
17298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: CCMP is used, but EAPOL-Key "
17308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"descriptor version (%d) is not 2", ver);
17318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->group_cipher != WPA_CIPHER_CCMP &&
17328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    !(key_info & WPA_KEY_INFO_KEY_TYPE)) {
17338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/* Earlier versions of IEEE 802.11i did not explicitly
17348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * require version 2 descriptor for all EAPOL-Key
17358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * packets, so allow group keys to use version 1 if
17368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * CCMP is not used for them. */
17378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
17388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Backwards compatibility: allow invalid "
17398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"version for non-CCMP group keys");
1740658fb4adb9458c3055c64a43833f1a9e89b4db74Jouni Malinen		} else if (ver == WPA_KEY_INFO_TYPE_AES_128_CMAC) {
1741658fb4adb9458c3055c64a43833f1a9e89b4db74Jouni Malinen			wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
1742658fb4adb9458c3055c64a43833f1a9e89b4db74Jouni Malinen				"WPA: Interoperability workaround: allow incorrect (should have been HMAC-SHA1), but stronger (is AES-128-CMAC), descriptor version to be used");
17438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else
17448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto out;
1745717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt	} else if (sm->pairwise_cipher == WPA_CIPHER_GCMP &&
1746717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt		   ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
174761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
174861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			"WPA: GCMP is used, but EAPOL-Key "
174961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			"descriptor version (%d) is not 2", ver);
175061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		goto out;
175161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
17528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_PEERKEY
17548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) {
17558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(peerkey->addr, src_addr, ETH_ALEN) == 0)
17568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
17578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!(key_info & WPA_KEY_INFO_SMK_MESSAGE) && peerkey) {
17608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!peerkey->initiator && peerkey->replay_counter_set &&
17618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    os_memcmp(key->replay_counter, peerkey->replay_counter,
17628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      WPA_REPLAY_COUNTER_LEN) <= 0) {
17638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
17648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"RSN: EAPOL-Key Replay Counter did not "
17658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"increase (STK) - dropping packet");
17668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto out;
17678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (peerkey->initiator) {
17688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u8 _tmp[WPA_REPLAY_COUNTER_LEN];
17698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(_tmp, key->replay_counter,
17708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  WPA_REPLAY_COUNTER_LEN);
17718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			inc_byte_array(_tmp, WPA_REPLAY_COUNTER_LEN);
17728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (os_memcmp(_tmp, peerkey->replay_counter,
17738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      WPA_REPLAY_COUNTER_LEN) != 0) {
17748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
17758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"RSN: EAPOL-Key Replay "
17768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"Counter did not match (STK) - "
17778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"dropping packet");
17788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				goto out;
17798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
17808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
17818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (peerkey && peerkey->initiator && (key_info & WPA_KEY_INFO_ACK)) {
17848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
17858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"RSN: Ack bit in key_info from STK peer");
17868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
17878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_PEERKEY */
17898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!peerkey && sm->rx_replay_counter_set &&
17918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(key->replay_counter, sm->rx_replay_counter,
17928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      WPA_REPLAY_COUNTER_LEN) <= 0) {
17938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
17948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: EAPOL-Key Replay Counter did not increase - "
17958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"dropping packet");
17968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
17978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!(key_info & (WPA_KEY_INFO_ACK | WPA_KEY_INFO_SMK_MESSAGE))
18008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_PEERKEY
18018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    && (peerkey == NULL || !peerkey->initiator)
18028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_PEERKEY */
18038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		) {
18048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
18058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: No Ack bit in key_info");
18068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
18078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (key_info & WPA_KEY_INFO_REQUEST) {
18108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
18118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: EAPOL-Key with Request bit - dropped");
18128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
18138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((key_info & WPA_KEY_INFO_MIC) && !peerkey &&
18168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wpa_supplicant_verify_eapol_key_mic(sm, key, ver, tmp, data_len))
18178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
18188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_PEERKEY
18208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((key_info & WPA_KEY_INFO_MIC) && peerkey &&
18218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    peerkey_verify_eapol_key_mic(sm, peerkey, key, ver, tmp, data_len))
18228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
18238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_PEERKEY */
18248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1825f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	if ((sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) &&
18268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
182743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		if (wpa_supplicant_decrypt_key_data(sm, key, ver, key_data,
182843cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt						    &key_data_len))
18298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto out;
18308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (key_info & WPA_KEY_INFO_KEY_TYPE) {
18338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) {
18348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
18358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Ignored EAPOL-Key (Pairwise) with "
18368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"non-zero key index");
18378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto out;
18388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
18398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (peerkey) {
18408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/* PeerKey 4-Way Handshake */
1841c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt			peerkey_rx_eapol_4way(sm, peerkey, key, key_info, ver,
1842c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt					      key_data, key_data_len);
18438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (key_info & WPA_KEY_INFO_MIC) {
18448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/* 3/4 4-Way Handshake */
184543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt			wpa_supplicant_process_3_of_4(sm, key, ver, key_data,
184643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt						      key_data_len);
18478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
18488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/* 1/4 4-Way Handshake */
18498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_supplicant_process_1_of_4(sm, src_addr, key,
185043cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt						      ver, key_data,
185143cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt						      key_data_len);
18528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
18538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (key_info & WPA_KEY_INFO_SMK_MESSAGE) {
18548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* PeerKey SMK Handshake */
185543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		peerkey_rx_eapol_smk(sm, src_addr, key, key_data_len, key_info,
18568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     ver);
18578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
18588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (key_info & WPA_KEY_INFO_MIC) {
18598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/* 1/2 Group Key Handshake */
18608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_supplicant_process_1_of_2(sm, src_addr, key,
186143cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt						      key_data, key_data_len,
186243cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt						      ver);
18638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
18648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
18658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: EAPOL-Key (Group) without Mic bit - "
18668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"dropped");
18678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
18688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = 1;
18718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtout:
18738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(tmp);
18748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
18758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_CTRL_IFACE
18798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u32 wpa_key_mgmt_suite(struct wpa_sm *sm)
18808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (sm->key_mgmt) {
18828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_KEY_MGMT_IEEE8021X:
1883f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		return ((sm->proto == WPA_PROTO_RSN ||
1884f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt			 sm->proto == WPA_PROTO_OSEN) ?
18858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			RSN_AUTH_KEY_MGMT_UNSPEC_802_1X :
18868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			WPA_AUTH_KEY_MGMT_UNSPEC_802_1X);
18878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_KEY_MGMT_PSK:
18888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return (sm->proto == WPA_PROTO_RSN ?
18898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X :
18908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X);
18918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
18928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_KEY_MGMT_FT_IEEE8021X:
18938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return RSN_AUTH_KEY_MGMT_FT_802_1X;
18948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_KEY_MGMT_FT_PSK:
18958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return RSN_AUTH_KEY_MGMT_FT_PSK;
18968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
18978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W
18988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_KEY_MGMT_IEEE8021X_SHA256:
18998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return RSN_AUTH_KEY_MGMT_802_1X_SHA256;
19008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_KEY_MGMT_PSK_SHA256:
19018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return RSN_AUTH_KEY_MGMT_PSK_SHA256;
19028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */
1903d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	case WPA_KEY_MGMT_CCKM:
1904d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		return (sm->proto == WPA_PROTO_RSN ?
1905d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			RSN_AUTH_KEY_MGMT_CCKM:
1906d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			WPA_AUTH_KEY_MGMT_CCKM);
19078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_KEY_MGMT_WPA_NONE:
19088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return WPA_AUTH_KEY_MGMT_NONE;
19098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
19108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
19118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define RSN_SUITE "%02x-%02x-%02x-%d"
19168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define RSN_SUITE_ARG(s) \
19178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt((s) >> 24) & 0xff, ((s) >> 16) & 0xff, ((s) >> 8) & 0xff, (s) & 0xff
19188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
19208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_get_mib - Dump text list of MIB entries
19218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
19228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Buffer for the list
19238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buflen: Length of the buffer
19248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Number of bytes written to buffer
19258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
19268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used fetch dot11 MIB variables.
19278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
19288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen)
19298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char pmkid_txt[PMKID_LEN * 2 + 1];
19318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int rsna, ret;
19328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
19338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->cur_pmksa) {
19358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_snprintf_hex(pmkid_txt, sizeof(pmkid_txt),
19368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 sm->cur_pmksa->pmkid, PMKID_LEN);
19378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
19388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pmkid_txt[0] = '\0';
19398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((wpa_key_mgmt_wpa_psk(sm->key_mgmt) ||
19418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt)) &&
19428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    sm->proto == WPA_PROTO_RSN)
19438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		rsna = 1;
19448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
19458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		rsna = 0;
19468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = os_snprintf(buf, buflen,
19488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dot11RSNAOptionImplemented=TRUE\n"
19498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dot11RSNAPreauthenticationImplemented=TRUE\n"
19508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dot11RSNAEnabled=%s\n"
19518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dot11RSNAPreauthenticationEnabled=%s\n"
19528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dot11RSNAConfigVersion=%d\n"
19538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dot11RSNAConfigPairwiseKeysSupported=5\n"
19548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dot11RSNAConfigGroupCipherSize=%d\n"
19558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dot11RSNAConfigPMKLifetime=%d\n"
19568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dot11RSNAConfigPMKReauthThreshold=%d\n"
19578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dot11RSNAConfigNumberOfPTKSAReplayCounters=1\n"
19588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dot11RSNAConfigSATimeout=%d\n",
19598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  rsna ? "TRUE" : "FALSE",
19608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  rsna ? "TRUE" : "FALSE",
19618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  RSN_VERSION,
19624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			  wpa_cipher_key_len(sm->group_cipher) * 8,
19638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sm->dot11RSNAConfigPMKLifetime,
19648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sm->dot11RSNAConfigPMKReauthThreshold,
19658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sm->dot11RSNAConfigSATimeout);
19668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret < 0 || (size_t) ret >= buflen)
19678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
19688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = ret;
19698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = os_snprintf(
19718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		buf + len, buflen - len,
19728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"dot11RSNAAuthenticationSuiteSelected=" RSN_SUITE "\n"
19738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"dot11RSNAPairwiseCipherSelected=" RSN_SUITE "\n"
19748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"dot11RSNAGroupCipherSelected=" RSN_SUITE "\n"
19758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"dot11RSNAPMKIDUsed=%s\n"
19768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"dot11RSNAAuthenticationSuiteRequested=" RSN_SUITE "\n"
19778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"dot11RSNAPairwiseCipherRequested=" RSN_SUITE "\n"
19788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"dot11RSNAGroupCipherRequested=" RSN_SUITE "\n"
19798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"dot11RSNAConfigNumberOfGTKSAReplayCounters=0\n"
19808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"dot11RSNA4WayHandshakeFailures=%u\n",
19818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		RSN_SUITE_ARG(wpa_key_mgmt_suite(sm)),
19824530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		RSN_SUITE_ARG(wpa_cipher_to_suite(sm->proto,
19834530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt						  sm->pairwise_cipher)),
19844530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		RSN_SUITE_ARG(wpa_cipher_to_suite(sm->proto,
19854530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt						  sm->group_cipher)),
19868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pmkid_txt,
19878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		RSN_SUITE_ARG(wpa_key_mgmt_suite(sm)),
19884530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		RSN_SUITE_ARG(wpa_cipher_to_suite(sm->proto,
19894530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt						  sm->pairwise_cipher)),
19904530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		RSN_SUITE_ARG(wpa_cipher_to_suite(sm->proto,
19914530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt						  sm->group_cipher)),
19928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->dot11RSNA4WayHandshakeFailures);
19938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret >= 0 && (size_t) ret < buflen)
19948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len += ret;
19958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return (int) len;
19978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE */
19998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_sm_pmksa_free_cb(struct rsn_pmksa_cache_entry *entry,
2002d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				 void *ctx, enum pmksa_free_reason reason)
20038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_sm *sm = ctx;
2005d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	int deauth = 0;
2006d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
2007d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: PMKSA cache entry free_cb: "
2008d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		MACSTR " reason=%d", MAC2STR(entry->aa), reason);
2009d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
2010d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (sm->cur_pmksa == entry) {
2011d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
2012d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			"RSN: %s current PMKSA entry",
2013d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			reason == PMKSA_REPLACE ? "replaced" : "removed");
2014d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		pmksa_cache_clear_current(sm);
2015d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
2016d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		/*
2017d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		 * If an entry is simply being replaced, there's no need to
2018d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		 * deauthenticate because it will be immediately re-added.
2019d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		 * This happens when EAP authentication is completed again
2020d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		 * (reauth or failed PMKSA caching attempt).
2021d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		 */
2022d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		if (reason != PMKSA_REPLACE)
2023d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			deauth = 1;
2024d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	}
20258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2026d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (reason == PMKSA_EXPIRE &&
20278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (sm->pmk_len == entry->pmk_len &&
20288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     os_memcmp(sm->pmk, entry->pmk, sm->pmk_len) == 0)) {
20298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
2030d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			"RSN: deauthenticating due to expired PMK");
2031d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		pmksa_cache_clear_current(sm);
2032d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		deauth = 1;
2033d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	}
20348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2035d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (deauth) {
20368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(sm->pmk, 0, sizeof(sm->pmk));
20378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
20388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
20438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_init - Initialize WPA state machine
20448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ctx: Context pointer for callbacks; this needs to be an allocated buffer
20458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the allocated WPA state machine data
20468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
20478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used to allocate a new WPA state machine and the returned
20488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * value is passed to all WPA state machine calls.
20498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
20508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_sm * wpa_sm_init(struct wpa_sm_ctx *ctx)
20518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_sm *sm;
20538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm = os_zalloc(sizeof(*sm));
20558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
20568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
20578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_init(&sm->pmksa_candidates);
20588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->renew_snonce = 1;
20598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->ctx = ctx;
20608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->dot11RSNAConfigPMKLifetime = 43200;
20628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->dot11RSNAConfigPMKReauthThreshold = 70;
20638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->dot11RSNAConfigSATimeout = 60;
20648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->pmksa = pmksa_cache_init(wpa_sm_pmksa_free_cb, sm, sm);
20668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->pmksa == NULL) {
20678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
20688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"RSN: PMKSA cache initialization failed");
20698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(sm);
20708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
20718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return sm;
20748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
20788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_deinit - Deinitialize WPA state machine
20798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
20808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
20818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_deinit(struct wpa_sm *sm)
20828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
20848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
20858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pmksa_cache_deinit(sm->pmksa);
20868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(wpa_sm_start_preauth, sm, NULL);
20878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL);
20888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sm->assoc_wpa_ie);
20898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sm->ap_wpa_ie);
20908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sm->ap_rsn_ie);
20918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sm->ctx);
20928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	peerkey_deinit(sm);
20938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
20948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sm->assoc_resp_ies);
20958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
20968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sm);
20978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
21018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_notify_assoc - Notify WPA state machine about association
21028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
21038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @bssid: The BSSID of the new association
21048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
21058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called to let WPA state machine know that the connection
21068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * was established.
21078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
21088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid)
21098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int clear_ptk = 1;
21118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
21138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
21148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
21168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"WPA: Association event - clear replay counter");
21178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(sm->bssid, bssid, ETH_ALEN);
21188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(sm->rx_replay_counter, 0, WPA_REPLAY_COUNTER_LEN);
21198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->rx_replay_counter_set = 0;
21208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->renew_snonce = 1;
21218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(sm->preauth_bssid, bssid, ETH_ALEN) == 0)
21228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		rsn_preauth_deinit(sm);
21238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
21258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_ft_is_completed(sm)) {
21268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
21278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Clear portValid to kick EAPOL state machine to re-enter
21288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * AUTHENTICATED state to get the EAPOL port Authorized.
21298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
21308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eapol_sm_notify_portValid(sm->eapol, FALSE);
21318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_key_neg_complete(sm, sm->bssid, 1);
21328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Prepare for the next transition */
21348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_ft_prepare_auth_request(sm, NULL);
21358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		clear_ptk = 0;
21378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
21398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (clear_ptk) {
21418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
21428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * IEEE 802.11, 8.4.10: Delete PTK SA on (re)association if
21438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * this is not part of a Fast BSS Transition.
21448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
21458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Clear old PTK");
21468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->ptk_set = 0;
214761593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		os_memset(&sm->ptk, 0, sizeof(sm->ptk));
21488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->tptk_set = 0;
214961593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		os_memset(&sm->tptk, 0, sizeof(sm->tptk));
21508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS
21538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_tdls_assoc(sm);
21548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS */
2155cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
2156cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#ifdef CONFIG_P2P
2157cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	os_memset(sm->p2p_ip_addr, 0, sizeof(sm->p2p_ip_addr));
2158cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#endif /* CONFIG_P2P */
21598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
21638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_notify_disassoc - Notify WPA state machine about disassociation
21648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
21658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
21668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called to let WPA state machine know that the connection
21678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * was lost. This will abort any existing pre-authentication session.
21688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
21698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_notify_disassoc(struct wpa_sm *sm)
21708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2171fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	peerkey_deinit(sm);
21728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rsn_preauth_deinit(sm);
2173d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	pmksa_cache_clear_current(sm);
21748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_sm_get_state(sm) == WPA_4WAY_HANDSHAKE)
21758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->dot11RSNA4WayHandshakeFailures++;
21768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS
21778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_tdls_disassoc(sm);
21788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS */
21798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
21838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_pmk - Set PMK
21848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
21858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pmk: The new PMK
21868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pmk_len: The length of the new PMK in bytes
21878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
21888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Configure the PMK for WPA state machine.
21898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
21908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len)
21918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
21938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
21948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->pmk_len = pmk_len;
21968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(sm->pmk, pmk, pmk_len);
21978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
21998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Set XXKey to be PSK for FT key derivation */
22008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->xxkey_len = pmk_len;
22018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(sm->xxkey, pmk, pmk_len);
22028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
22038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
22078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_pmk_from_pmksa - Set PMK based on the current PMKSA
22088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
22098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
22108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Take the PMK from the current PMKSA into use. If no PMKSA is active, the PMK
22118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * will be cleared.
22128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
22138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_set_pmk_from_pmksa(struct wpa_sm *sm)
22148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
22168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
22178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->cur_pmksa) {
22198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->pmk_len = sm->cur_pmksa->pmk_len;
22208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(sm->pmk, sm->cur_pmksa->pmk, sm->pmk_len);
22218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
22228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->pmk_len = PMK_LEN;
22238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(sm->pmk, 0, PMK_LEN);
22248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
22298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_fast_reauth - Set fast reauthentication (EAP) enabled/disabled
22308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
22318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @fast_reauth: Whether fast reauthentication (EAP) is allowed
22328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
22338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_set_fast_reauth(struct wpa_sm *sm, int fast_reauth)
22348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm)
22368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->fast_reauth = fast_reauth;
22378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
22418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_scard_ctx - Set context pointer for smartcard callbacks
22428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
22438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @scard_ctx: Context pointer for smartcard related callback functions
22448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
22458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_set_scard_ctx(struct wpa_sm *sm, void *scard_ctx)
22468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
22488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
22498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->scard_ctx = scard_ctx;
22508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->preauth_eapol)
22518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eapol_sm_register_scard_ctx(sm->preauth_eapol, scard_ctx);
22528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
22568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_config - Notification of current configration change
22578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
22588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @config: Pointer to current network configuration
22598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
22608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Notify WPA state machine that configuration has changed. config will be
22618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * stored as a backpointer to network configuration. This can be %NULL to clear
22628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the stored pointed.
22638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
22648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_set_config(struct wpa_sm *sm, struct rsn_supp_config *config)
22658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!sm)
22678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
22688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config) {
22708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->network_ctx = config->network_ctx;
22718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->peerkey_enabled = config->peerkey_enabled;
22728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->allowed_pairwise_cipher = config->allowed_pairwise_cipher;
22738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->proactive_key_caching = config->proactive_key_caching;
22748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eap_workaround = config->eap_workaround;
22758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eap_conf_ctx = config->eap_conf_ctx;
22768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (config->ssid) {
22778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(sm->ssid, config->ssid, config->ssid_len);
22788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->ssid_len = config->ssid_len;
22798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else
22808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->ssid_len = 0;
22818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->wpa_ptk_rekey = config->wpa_ptk_rekey;
2282cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		sm->p2p = config->p2p;
22838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
22848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->network_ctx = NULL;
22858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->peerkey_enabled = 0;
22868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->allowed_pairwise_cipher = 0;
22878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->proactive_key_caching = 0;
22888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eap_workaround = 0;
22898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eap_conf_ctx = NULL;
22908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->ssid_len = 0;
22918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->wpa_ptk_rekey = 0;
2292cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		sm->p2p = 0;
22938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
22988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_own_addr - Set own MAC address
22998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
23008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: Own MAC address
23018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
23028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_set_own_addr(struct wpa_sm *sm, const u8 *addr)
23038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm)
23058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(sm->own_addr, addr, ETH_ALEN);
23068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
23108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_ifname - Set network interface name
23118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
23128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ifname: Interface name
23138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @bridge_ifname: Optional bridge interface name (for pre-auth)
23148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
23158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_set_ifname(struct wpa_sm *sm, const char *ifname,
23168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       const char *bridge_ifname)
23178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm) {
23198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->ifname = ifname;
23208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->bridge_ifname = bridge_ifname;
23218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
23268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_eapol - Set EAPOL state machine pointer
23278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
23288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @eapol: Pointer to EAPOL state machine allocated with eapol_sm_init()
23298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
23308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_set_eapol(struct wpa_sm *sm, struct eapol_sm *eapol)
23318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm)
23338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eapol = eapol;
23348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
23388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_param - Set WPA state machine parameters
23398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
23408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @param: Parameter field
23418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @value: Parameter value
23428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
23438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
23448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param,
23458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     unsigned int value)
23468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret = 0;
23488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
23508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
23518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (param) {
23538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case RSNA_PMK_LIFETIME:
23548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (value > 0)
23558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->dot11RSNAConfigPMKLifetime = value;
23568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
23578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = -1;
23588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
23598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case RSNA_PMK_REAUTH_THRESHOLD:
23608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (value > 0 && value <= 100)
23618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->dot11RSNAConfigPMKReauthThreshold = value;
23628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
23638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = -1;
23648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
23658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case RSNA_SA_TIMEOUT:
23668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (value > 0)
23678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->dot11RSNAConfigSATimeout = value;
23688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
23698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = -1;
23708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
23718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_PARAM_PROTO:
23728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->proto = value;
23738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
23748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_PARAM_PAIRWISE:
23758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->pairwise_cipher = value;
23768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
23778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_PARAM_GROUP:
23788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->group_cipher = value;
23798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
23808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_PARAM_KEY_MGMT:
23818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->key_mgmt = value;
23828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
23838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W
23848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_PARAM_MGMT_GROUP:
23858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->mgmt_group_cipher = value;
23868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
23878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */
23888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_PARAM_RSN_ENABLED:
23898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->rsn_enabled = value;
23908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
23918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_PARAM_MFP:
23928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->mfp = value;
23938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
23948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
23958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
23968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
23998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
24038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_get_status - Get WPA state machine
24048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
24058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Buffer for status information
24068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buflen: Maximum buffer length
24078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @verbose: Whether to include verbose status information
24088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Number of bytes written to buf.
24098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
24108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Query WPA state machine for status information. This function fills in
24118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * a text area with current status information. If the buffer (buf) is not
24128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * large enough, status information will be truncated to fit the buffer.
24138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
24148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_get_status(struct wpa_sm *sm, char *buf, size_t buflen,
24158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      int verbose)
24168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *pos = buf, *end = buf + buflen;
24188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
24198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = os_snprintf(pos, end - pos,
24218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "pairwise_cipher=%s\n"
24228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "group_cipher=%s\n"
24238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "key_mgmt=%s\n",
24248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  wpa_cipher_txt(sm->pairwise_cipher),
24258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  wpa_cipher_txt(sm->group_cipher),
24268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  wpa_key_mgmt_txt(sm->key_mgmt, sm->proto));
24278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret < 0 || ret >= end - pos)
24288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return pos - buf;
24298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += ret;
2430d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
2431d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (sm->mfp != NO_MGMT_FRAME_PROTECTION && sm->ap_rsn_ie) {
2432d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		struct wpa_ie_data rsn;
2433d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		if (wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, &rsn)
2434d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		    >= 0 &&
2435d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		    rsn.capabilities & (WPA_CAPABILITY_MFPR |
2436d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt					WPA_CAPABILITY_MFPC)) {
2437d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			ret = os_snprintf(pos, end - pos, "pmf=%d\n",
2438d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt					  (rsn.capabilities &
2439d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt					   WPA_CAPABILITY_MFPR) ? 2 : 1);
2440d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			if (ret < 0 || ret >= end - pos)
2441d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				return pos - buf;
2442d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			pos += ret;
2443d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		}
2444d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	}
2445d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
24468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return pos - buf;
24478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2450f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidtint wpa_sm_pmf_enabled(struct wpa_sm *sm)
2451f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt{
2452f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt	struct wpa_ie_data rsn;
2453f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt
2454f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt	if (sm->mfp == NO_MGMT_FRAME_PROTECTION || !sm->ap_rsn_ie)
2455f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt		return 0;
2456f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt
2457f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt	if (wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, &rsn) >= 0 &&
2458f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt	    rsn.capabilities & (WPA_CAPABILITY_MFPR | WPA_CAPABILITY_MFPC))
2459f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt		return 1;
2460f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt
2461f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt	return 0;
2462f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt}
2463f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt
2464f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt
24658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
24668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_assoc_wpa_ie_default - Generate own WPA/RSN IE from configuration
24678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
24688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_ie: Pointer to buffer for WPA/RSN IE
24698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_ie_len: Pointer to the length of the wpa_ie buffer
24708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
24718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
24728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_set_assoc_wpa_ie_default(struct wpa_sm *sm, u8 *wpa_ie,
24738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    size_t *wpa_ie_len)
24748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
24768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
24788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
24798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = wpa_gen_wpa_ie(sm, wpa_ie, *wpa_ie_len);
24818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0)
24828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
24838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*wpa_ie_len = res;
24848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "WPA: Set own WPA IE default",
24868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    wpa_ie, *wpa_ie_len);
24878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->assoc_wpa_ie == NULL) {
24898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
24908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Make a copy of the WPA/RSN IE so that 4-Way Handshake gets
24918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * the correct version of the IE even if PMKSA caching is
24928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * aborted (which would remove PMKID from IE generation).
24938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
24948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->assoc_wpa_ie = os_malloc(*wpa_ie_len);
24958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->assoc_wpa_ie == NULL)
24968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
24978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(sm->assoc_wpa_ie, wpa_ie, *wpa_ie_len);
24998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->assoc_wpa_ie_len = *wpa_ie_len;
25008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
25038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
25078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_assoc_wpa_ie - Set own WPA/RSN IE from (Re)AssocReq
25088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
25098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ie: Pointer to IE data (starting from id)
25108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: IE length
25118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
25128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
25138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Inform WPA state machine about the WPA/RSN IE used in (Re)Association
25148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Request frame. The IE will be used to override the default value generated
25158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * with wpa_sm_set_assoc_wpa_ie_default().
25168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
25178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_set_assoc_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len)
25188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
25208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
25218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sm->assoc_wpa_ie);
25238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie == NULL || len == 0) {
25248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
25258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: clearing own WPA/RSN IE");
25268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->assoc_wpa_ie = NULL;
25278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->assoc_wpa_ie_len = 0;
25288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
25298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "WPA: set own WPA/RSN IE", ie, len);
25308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->assoc_wpa_ie = os_malloc(len);
25318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->assoc_wpa_ie == NULL)
25328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
25338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(sm->assoc_wpa_ie, ie, len);
25358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->assoc_wpa_ie_len = len;
25368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
25398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
25438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_ap_wpa_ie - Set AP WPA IE from Beacon/ProbeResp
25448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
25458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ie: Pointer to IE data (starting from id)
25468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: IE length
25478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
25488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
25498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Inform WPA state machine about the WPA IE used in Beacon / Probe Response
25508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * frame.
25518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
25528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_set_ap_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len)
25538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
25558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
25568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sm->ap_wpa_ie);
25588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie == NULL || len == 0) {
25598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
25608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: clearing AP WPA IE");
25618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->ap_wpa_ie = NULL;
25628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->ap_wpa_ie_len = 0;
25638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
25648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "WPA: set AP WPA IE", ie, len);
25658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->ap_wpa_ie = os_malloc(len);
25668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->ap_wpa_ie == NULL)
25678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
25688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(sm->ap_wpa_ie, ie, len);
25708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->ap_wpa_ie_len = len;
25718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
25748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
25788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_ap_rsn_ie - Set AP RSN IE from Beacon/ProbeResp
25798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
25808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ie: Pointer to IE data (starting from id)
25818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: IE length
25828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
25838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
25848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Inform WPA state machine about the RSN IE used in Beacon / Probe Response
25858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * frame.
25868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
25878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, size_t len)
25888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
25908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
25918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sm->ap_rsn_ie);
25938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie == NULL || len == 0) {
25948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
25958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: clearing AP RSN IE");
25968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->ap_rsn_ie = NULL;
25978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->ap_rsn_ie_len = 0;
25988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
25998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "WPA: set AP RSN IE", ie, len);
26008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->ap_rsn_ie = os_malloc(len);
26018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->ap_rsn_ie == NULL)
26028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
26038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(sm->ap_rsn_ie, ie, len);
26058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->ap_rsn_ie_len = len;
26068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
26098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
26138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_parse_own_wpa_ie - Parse own WPA/RSN IE
26148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
26158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Pointer to data area for parsing results
26168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 if IE is not known, or -2 on parsing failure
26178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
26188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Parse the contents of the own WPA or RSN IE from (Re)AssocReq and write the
26198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * parsed data into data.
26208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
26218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_parse_own_wpa_ie(struct wpa_sm *sm, struct wpa_ie_data *data)
26228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
26248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
26258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->assoc_wpa_ie == NULL) {
26278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
26288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: No WPA/RSN IE available from association info");
26298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
26308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_parse_wpa_ie(sm->assoc_wpa_ie, sm->assoc_wpa_ie_len, data))
26328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -2;
26338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
26348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_pmksa_cache_list(struct wpa_sm *sm, char *buf, size_t len)
26388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return pmksa_cache_list(sm->pmksa, buf, len);
26408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
264321de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt#ifdef CONFIG_TESTING_OPTIONS
26448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_drop_sa(struct wpa_sm *sm)
26458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Clear old PMK and PTK");
26478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->ptk_set = 0;
26488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->tptk_set = 0;
26498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(sm->pmk, 0, sizeof(sm->pmk));
26508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&sm->ptk, 0, sizeof(sm->ptk));
26518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&sm->tptk, 0, sizeof(sm->tptk));
26528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
265321de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt#endif /* CONFIG_TESTING_OPTIONS */
26548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_has_ptk(struct wpa_sm *sm)
26578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
26598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
26608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return sm->ptk_set;
26618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
26631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
26641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtvoid wpa_sm_update_replay_ctr(struct wpa_sm *sm, const u8 *replay_ctr)
26651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
26661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	os_memcpy(sm->rx_replay_counter, replay_ctr, WPA_REPLAY_COUNTER_LEN);
26671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
26681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
26691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
26701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtvoid wpa_sm_pmksa_cache_flush(struct wpa_sm *sm, void *network_ctx)
26711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
2672f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt	pmksa_cache_flush(sm->pmksa, network_ctx, NULL, 0);
26731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
267461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
267561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
2676a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt#ifdef CONFIG_WNM
267761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 subelem_id, u8 *buf)
267861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
267961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	u16 keyinfo;
268061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	u8 keylen;  /* plaintext key len */
268161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	u8 *key_rsc;
268261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
268361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (subelem_id == WNM_SLEEP_SUBELEM_GTK) {
268461593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		struct wpa_gtk_data gd;
268561593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt
268661593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		os_memset(&gd, 0, sizeof(gd));
268761593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		keylen = wpa_cipher_key_len(sm->group_cipher);
268861593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		gd.key_rsc_len = wpa_cipher_rsc_len(sm->group_cipher);
268961593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		gd.alg = wpa_cipher_to_alg(sm->group_cipher);
269061593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		if (gd.alg == WPA_ALG_NONE) {
269161593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt			wpa_printf(MSG_DEBUG, "Unsupported group cipher suite");
269261593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt			return -1;
269361593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		}
269461593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt
269561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		key_rsc = buf + 5;
2696a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		keyinfo = WPA_GET_LE16(buf + 2);
269761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		gd.gtk_len = keylen;
269861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (gd.gtk_len != buf[4]) {
269961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpa_printf(MSG_DEBUG, "GTK len mismatch len %d vs %d",
270061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				   gd.gtk_len, buf[4]);
270161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
270261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
270361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		gd.keyidx = keyinfo & 0x03; /* B0 - B1 */
270461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		gd.tx = wpa_supplicant_gtk_tx_bit_workaround(
270561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		         sm, !!(keyinfo & WPA_KEY_INFO_TXRX));
270661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
2707a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		os_memcpy(gd.gtk, buf + 13, gd.gtk_len);
270861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
270961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpa_hexdump_key(MSG_DEBUG, "Install GTK (WNM SLEEP)",
271061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				gd.gtk, gd.gtk_len);
271161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (wpa_supplicant_install_gtk(sm, &gd, key_rsc)) {
271261593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt			os_memset(&gd, 0, sizeof(gd));
271361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpa_printf(MSG_DEBUG, "Failed to install the GTK in "
271461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				   "WNM mode");
271561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
271661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
271761593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		os_memset(&gd, 0, sizeof(gd));
271861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_IEEE80211W
271961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else if (subelem_id == WNM_SLEEP_SUBELEM_IGTK) {
272061593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		struct wpa_igtk_kde igd;
272161593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		u16 keyidx;
272261593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt
272361593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		os_memset(&igd, 0, sizeof(igd));
2724b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt		keylen = wpa_cipher_key_len(sm->mgmt_group_cipher);
272561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		os_memcpy(igd.keyid, buf + 2, 2);
272661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		os_memcpy(igd.pn, buf + 4, 6);
272761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
272861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		keyidx = WPA_GET_LE16(igd.keyid);
2729b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt		os_memcpy(igd.igtk, buf + 10, keylen);
273061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
273161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpa_hexdump_key(MSG_DEBUG, "Install IGTK (WNM SLEEP)",
2732b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt				igd.igtk, keylen);
2733b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt		if (wpa_sm_set_key(sm, wpa_cipher_to_alg(sm->mgmt_group_cipher),
2734b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt				   broadcast_ether_addr,
273561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				   keyidx, 0, igd.pn, sizeof(igd.pn),
2736b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt				   igd.igtk, keylen) < 0) {
273761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpa_printf(MSG_DEBUG, "Failed to install the IGTK in "
273861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				   "WNM mode");
273961593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt			os_memset(&igd, 0, sizeof(igd));
274061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
274161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
274261593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		os_memset(&igd, 0, sizeof(igd));
274361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_IEEE80211W */
274461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else {
274561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpa_printf(MSG_DEBUG, "Unknown element id");
274661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return -1;
274761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
274861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
274961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
275061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
2751a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt#endif /* CONFIG_WNM */
2752fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt
2753fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt
2754fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt#ifdef CONFIG_PEERKEY
2755fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidtint wpa_sm_rx_eapol_peerkey(struct wpa_sm *sm, const u8 *src_addr,
2756fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			    const u8 *buf, size_t len)
2757fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt{
2758fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	struct wpa_peerkey *peerkey;
2759fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt
2760fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) {
2761fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		if (os_memcmp(peerkey->addr, src_addr, ETH_ALEN) == 0)
2762fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			break;
2763fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	}
2764fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt
2765fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	if (!peerkey)
2766fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		return 0;
2767fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt
2768fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	wpa_sm_rx_eapol(sm, src_addr, buf, len);
2769fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt
2770fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	return 1;
2771fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt}
2772fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt#endif /* CONFIG_PEERKEY */
2773cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
2774cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
2775cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#ifdef CONFIG_P2P
2776cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
2777cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtint wpa_sm_get_p2p_ip_addr(struct wpa_sm *sm, u8 *buf)
2778cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt{
2779cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (sm == NULL || WPA_GET_BE32(sm->p2p_ip_addr) == 0)
2780cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		return -1;
2781cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	os_memcpy(buf, sm->p2p_ip_addr, 3 * 4);
2782cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	return 0;
2783cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt}
2784cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
2785cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#endif /* CONFIG_P2P */
2786