wpa.c revision cce06667447b5aec83452adb0c15100ada531095
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
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_key_mgmt_ft(sm->key_mgmt) || wpa_key_mgmt_sha256(sm->key_mgmt))
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ver = WPA_KEY_INFO_TYPE_AES_128_CMAC;
9461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	else if (sm->pairwise_cipher != WPA_CIPHER_TKIP)
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_sm_get_bssid(sm, bssid) < 0) {
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Failed to read BSSID for EAPOL-Key request");
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  sizeof(*reply), &rlen, (void *) &reply);
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (rbuf == NULL)
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	reply->type = sm->proto == WPA_PROTO_RSN ?
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key_info = WPA_KEY_INFO_REQUEST | ver;
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->ptk_set)
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_info |= WPA_KEY_INFO_MIC;
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (error)
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_info |= WPA_KEY_INFO_ERROR;
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pairwise)
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_info |= WPA_KEY_INFO_KEY_TYPE;
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE16(reply->key_info, key_info);
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE16(reply->key_length, 0);
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(reply->replay_counter, sm->request_counter,
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  WPA_REPLAY_COUNTER_LEN);
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN);
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE16(reply->key_data_length, 0);
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"WPA: Sending EAPOL-Key Request (error=%d "
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"pairwise=%d ptk_set=%d len=%lu)",
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		error, pairwise, sm->ptk_set, (unsigned long) rlen);
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_eapol_key_send(sm, sm->ptk.kck, ver, bssid, ETH_P_EAPOL,
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   rbuf, rlen, key_info & WPA_KEY_INFO_MIC ?
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   reply->key_mic : NULL);
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_get_pmk(struct wpa_sm *sm,
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  const unsigned char *src_addr,
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  const u8 *pmkid)
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int abort_cached = 0;
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pmkid && !sm->cur_pmksa) {
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* When using drivers that generate RSN IE, wpa_supplicant may
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * not have enough time to get the association information
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * event before receiving this 1/4 message, so try to find a
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * matching PMKSA cache entry here. */
148c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		sm->cur_pmksa = pmksa_cache_get(sm->pmksa, src_addr, pmkid,
149c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt						NULL);
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->cur_pmksa) {
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"RSN: found matching PMKID from PMKSA cache");
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"RSN: no matching PMKID found");
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			abort_cached = 1;
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pmkid && sm->cur_pmksa &&
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(pmkid, sm->cur_pmksa->pmkid, PMKID_LEN) == 0) {
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "RSN: matched PMKID", pmkid, PMKID_LEN);
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_sm_set_pmk_from_pmksa(sm);
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump_key(MSG_DEBUG, "RSN: PMK from PMKSA cache",
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				sm->pmk, sm->pmk_len);
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eapol_sm_notify_cached(sm->eapol);
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->xxkey_len = 0;
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt) && sm->eapol) {
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int res, pmk_len;
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pmk_len = PMK_LEN;
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = eapol_sm_get_key(sm->eapol, sm->pmk, PMK_LEN);
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res) {
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/*
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * EAP-LEAP is an exception from other EAP methods: it
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * uses only 16-byte PMK.
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 */
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			res = eapol_sm_get_key(sm->eapol, sm->pmk, 16);
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pmk_len = 16;
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u8 buf[2 * PMK_LEN];
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (eapol_sm_get_key(sm->eapol, buf, 2 * PMK_LEN) == 0)
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			{
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				os_memcpy(sm->xxkey, buf + PMK_LEN, PMK_LEN);
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				sm->xxkey_len = PMK_LEN;
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				os_memset(buf, 0, sizeof(buf));
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res == 0) {
19361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			struct rsn_pmksa_cache_entry *sa = NULL;
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump_key(MSG_DEBUG, "WPA: PMK from EAPOL state "
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"machines", sm->pmk, pmk_len);
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->pmk_len = pmk_len;
197c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt			if (sm->proto == WPA_PROTO_RSN &&
198c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt			    !wpa_key_mgmt_ft(sm->key_mgmt)) {
19961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				sa = pmksa_cache_add(sm->pmksa,
20061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt						     sm->pmk, pmk_len,
20161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt						     src_addr, sm->own_addr,
20261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt						     sm->network_ctx,
20361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt						     sm->key_mgmt);
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (!sm->cur_pmksa && pmkid &&
206c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			    pmksa_cache_get(sm->pmksa, src_addr, pmkid, NULL))
207c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			{
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"RSN: the new PMK matches with the "
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"PMKID");
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				abort_cached = 0;
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
21361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
21461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			if (!sm->cur_pmksa)
21561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				sm->cur_pmksa = sa;
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Failed to get master session key from "
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"EAPOL state machines - key handshake "
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"aborted");
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (sm->cur_pmksa) {
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"RSN: Cancelled PMKSA caching "
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"attempt");
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				sm->cur_pmksa = NULL;
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				abort_cached = 1;
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			} else if (!abort_cached) {
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return -1;
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
233c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	if (abort_cached && wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt) &&
234c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	    !wpa_key_mgmt_ft(sm->key_mgmt)) {
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Send EAPOL-Start to trigger full EAP authentication. */
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		u8 *buf;
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		size_t buflen;
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"RSN: no PMKSA entry found - trigger "
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"full EAP authentication");
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		buf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_START,
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 NULL, 0, &buflen, NULL);
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (buf) {
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_sm_ether_send(sm, sm->bssid, ETH_P_EAPOL,
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  buf, buflen);
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(buf);
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -2;
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_supplicant_send_2_of_4 - Send message 2 of WPA/RSN 4-Way Handshake
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @dst: Destination address for the frame
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @key: Pointer to the EAPOL-Key frame header
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ver: Version bits from EAPOL-Key Key Info
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @nonce: Nonce value for the EAPOL-Key frame
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_ie: WPA/RSN IE
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_ie_len: Length of the WPA/RSN IE
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ptk: PTK to use for keyed hash and encryption
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       const struct wpa_eapol_key *key,
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       int ver, const u8 *nonce,
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       const u8 *wpa_ie, size_t wpa_ie_len,
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       struct wpa_ptk *ptk)
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t rlen;
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_eapol_key *reply;
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *rbuf;
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *rsn_ie_buf = NULL;
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_ie == NULL) {
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: No wpa_ie set - "
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"cannot generate msg 2/4");
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_key_mgmt_ft(sm->key_mgmt)) {
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int res;
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Add PMKR1Name into RSN IE (PMKID-List) and add MDIE and
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * FTIE from (Re)Association Response.
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		rsn_ie_buf = os_malloc(wpa_ie_len + 2 + 2 + PMKID_LEN +
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       sm->assoc_resp_ies_len);
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (rsn_ie_buf == NULL)
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(rsn_ie_buf, wpa_ie, wpa_ie_len);
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = wpa_insert_pmkid(rsn_ie_buf, wpa_ie_len,
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       sm->pmk_r1_name);
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res < 0) {
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(rsn_ie_buf);
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_ie_len += res;
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->assoc_resp_ies) {
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(rsn_ie_buf + wpa_ie_len, sm->assoc_resp_ies,
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  sm->assoc_resp_ies_len);
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_ie_len += sm->assoc_resp_ies_len;
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_ie = rsn_ie_buf;
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "WPA: WPA IE for msg 2/4", wpa_ie, wpa_ie_len);
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY,
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  NULL, sizeof(*reply) + wpa_ie_len,
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  &rlen, (void *) &reply);
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (rbuf == NULL) {
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(rsn_ie_buf);
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	reply->type = sm->proto == WPA_PROTO_RSN ?
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE16(reply->key_info,
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_MIC);
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->proto == WPA_PROTO_RSN)
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		WPA_PUT_BE16(reply->key_length, 0);
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(reply->key_length, key->key_length, 2);
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(reply->replay_counter, key->replay_counter,
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  WPA_REPLAY_COUNTER_LEN);
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "WPA: Replay Counter", reply->replay_counter,
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    WPA_REPLAY_COUNTER_LEN);
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE16(reply->key_data_length, wpa_ie_len);
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(reply + 1, wpa_ie, wpa_ie_len);
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(rsn_ie_buf);
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(reply->key_nonce, nonce, WPA_NONCE_LEN);
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 2/4");
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_eapol_key_send(sm, ptk->kck, ver, dst, ETH_P_EAPOL,
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   rbuf, rlen, reply->key_mic);
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr,
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  const struct wpa_eapol_key *key,
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  struct wpa_ptk *ptk)
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
35961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t ptk_len = sm->pairwise_cipher != WPA_CIPHER_TKIP ? 48 : 64;
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_key_mgmt_ft(sm->key_mgmt))
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return wpa_derive_ptk_ft(sm, src_addr, key, ptk, ptk_len);
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_pmk_to_ptk(sm->pmk, sm->pmk_len, "Pairwise key expansion",
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       sm->own_addr, sm->bssid, sm->snonce, key->key_nonce,
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       (u8 *) ptk, ptk_len,
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       wpa_key_mgmt_sha256(sm->key_mgmt));
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_process_1_of_4(struct wpa_sm *sm,
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  const unsigned char *src_addr,
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  const struct wpa_eapol_key *key,
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  u16 ver)
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_eapol_ie_parse ie;
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ptk *ptk;
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 buf[8];
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_sm_get_network_ctx(sm) == NULL) {
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: No SSID info "
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"found (msg 1 of 4)");
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE);
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: RX message 1 of 4-Way "
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"Handshake from " MACSTR " (ver=%d)", MAC2STR(src_addr), ver);
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&ie, 0, sizeof(ie));
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->proto == WPA_PROTO_RSN) {
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* RSN: msg 1/4 should contain PMKID for the selected PMK */
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		const u8 *_buf = (const u8 *) (key + 1);
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		size_t len = WPA_GET_BE16(key->key_data_length);
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "RSN: msg 1/4 key data", _buf, len);
4001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (wpa_supplicant_parse_ies(_buf, len, &ie) < 0)
4011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			goto failed;
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ie.pmkid) {
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump(MSG_DEBUG, "RSN: PMKID from "
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    "Authenticator", ie.pmkid, PMKID_LEN);
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = wpa_supplicant_get_pmk(sm, src_addr, ie.pmkid);
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res == -2) {
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: Do not reply to "
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"msg 1/4 - requesting full EAP authentication");
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res)
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->renew_snonce) {
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (random_get_bytes(sm->snonce, WPA_NONCE_LEN)) {
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Failed to get random data for SNonce");
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto failed;
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->renew_snonce = 0;
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "WPA: Renewed SNonce",
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    sm->snonce, WPA_NONCE_LEN);
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Calculate PTK which will be stored as a temporary PTK until it has
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * been verified when processing message 3/4. */
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ptk = &sm->tptk;
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_derive_ptk(sm, src_addr, key, ptk);
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Supplicant: swap tx/rx Mic keys */
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(buf, ptk->u.auth.tx_mic_key, 8);
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(ptk->u.auth.tx_mic_key, ptk->u.auth.rx_mic_key, 8);
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(ptk->u.auth.rx_mic_key, buf, 8);
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->tptk_set = 1;
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_supplicant_send_2_of_4(sm, sm->bssid, key, ver, sm->snonce,
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       sm->assoc_wpa_ie, sm->assoc_wpa_ie_len,
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       ptk))
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(sm->anonce, key->key_nonce, WPA_NONCE_LEN);
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return;
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfailed:
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_sm_start_preauth(void *eloop_ctx, void *timeout_ctx)
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_sm *sm = eloop_ctx;
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rsn_preauth_candidate_process(sm);
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_key_neg_complete(struct wpa_sm *sm,
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    const u8 *addr, int secure)
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"WPA: Key negotiation completed with "
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MACSTR " [PTK=%s GTK=%s]", MAC2STR(addr),
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_cipher_txt(sm->pairwise_cipher),
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_cipher_txt(sm->group_cipher));
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_sm_cancel_auth_timeout(sm);
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_sm_set_state(sm, WPA_COMPLETED);
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (secure) {
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_sm_mlme_setprotection(
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm, addr, MLME_SETPROTECTION_PROTECT_TYPE_RX_TX,
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eapol_sm_notify_portValid(sm->eapol, TRUE);
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_key_mgmt_wpa_psk(sm->key_mgmt))
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eapol_sm_notify_eap_success(sm->eapol, TRUE);
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Start preauthentication after a short wait to avoid a
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * possible race condition between the data receive and key
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * configuration after the 4-Way Handshake. This increases the
4801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * likelihood of the first preauth EAPOL-Start frame getting to
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * the target AP.
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(1, 0, wpa_sm_start_preauth, sm, NULL);
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->cur_pmksa && sm->cur_pmksa->opportunistic) {
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"RSN: Authenticator accepted "
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"opportunistic PMKSA entry - marking it valid");
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->cur_pmksa->opportunistic = 0;
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_key_mgmt_ft(sm->key_mgmt)) {
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Prepare for the next transition */
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_ft_prepare_auth_request(sm, NULL);
4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_sm_rekey_ptk(void *eloop_ctx, void *timeout_ctx)
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_sm *sm = eloop_ctx;
5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Request PTK rekeying");
5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_sm_key_request(sm, 0, 1);
5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_install_ptk(struct wpa_sm *sm,
5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const struct wpa_eapol_key *key)
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int keylen, rsclen;
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum wpa_alg alg;
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *key_rsc;
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 null_rsc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"WPA: Installing PTK to the driver");
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5214530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (sm->pairwise_cipher == WPA_CIPHER_NONE) {
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Pairwise Cipher "
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Suite: NONE - do not use pairwise keys");
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
5254530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
5264530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
5274530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (!wpa_cipher_valid_pairwise(sm->pairwise_cipher)) {
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: Unsupported pairwise cipher %d",
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->pairwise_cipher);
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5344530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	alg = wpa_cipher_to_alg(sm->pairwise_cipher);
5354530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	keylen = wpa_cipher_key_len(sm->pairwise_cipher);
5364530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	rsclen = wpa_cipher_rsc_len(sm->pairwise_cipher);
5374530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->proto == WPA_PROTO_RSN) {
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_rsc = null_rsc;
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_rsc = key->key_rsc;
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "WPA: RSC", key_rsc, rsclen);
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_sm_set_key(sm, alg, sm->bssid, 0, 1, key_rsc, rsclen,
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (u8 *) sm->ptk.tk1, keylen) < 0) {
5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: Failed to set PTK to the "
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"driver (alg=%d keylen=%d bssid=" MACSTR ")",
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			alg, keylen, MAC2STR(sm->bssid));
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->wpa_ptk_rekey) {
5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL);
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(sm->wpa_ptk_rekey, 0, wpa_sm_rekey_ptk,
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       sm, NULL);
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_check_group_cipher(struct wpa_sm *sm,
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     int group_cipher,
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     int keylen, int maxkeylen,
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     int *key_rsc_len,
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     enum wpa_alg *alg)
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5704530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	int klen;
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5724530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	*alg = wpa_cipher_to_alg(group_cipher);
5734530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (*alg == WPA_ALG_NONE) {
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: Unsupported Group Cipher %d",
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			group_cipher);
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5794530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	*key_rsc_len = wpa_cipher_rsc_len(group_cipher);
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5814530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	klen = wpa_cipher_key_len(group_cipher);
5824530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (keylen != klen || maxkeylen < klen) {
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: Unsupported %s Group Cipher key length %d (%d)",
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_cipher_txt(group_cipher), keylen, maxkeylen);
5864530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return -1;
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5884530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	return 0;
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_gtk_data {
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum wpa_alg alg;
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int tx, key_rsc_len, keyidx;
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 gtk[32];
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int gtk_len;
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_install_gtk(struct wpa_sm *sm,
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const struct wpa_gtk_data *gd,
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const u8 *key_rsc)
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *_gtk = gd->gtk;
6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 gtk_buf[32];
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_key(MSG_DEBUG, "WPA: Group Key", gd->gtk, gd->gtk_len);
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"WPA: Installing GTK to the driver (keyidx=%d tx=%d len=%d)",
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		gd->keyidx, gd->tx, gd->gtk_len);
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "WPA: RSC", key_rsc, gd->key_rsc_len);
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->group_cipher == WPA_CIPHER_TKIP) {
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Swap Tx/Rx keys for Michael MIC */
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(gtk_buf, gd->gtk, 16);
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(gtk_buf + 16, gd->gtk + 24, 8);
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(gtk_buf + 24, gd->gtk + 16, 8);
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		_gtk = gtk_buf;
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->pairwise_cipher == WPA_CIPHER_NONE) {
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_sm_set_key(sm, gd->alg, NULL,
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   gd->keyidx, 1, key_rsc, gd->key_rsc_len,
6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   _gtk, gd->gtk_len) < 0) {
6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Failed to set GTK to the driver "
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"(Group only)");
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (wpa_sm_set_key(sm, gd->alg, broadcast_ether_addr,
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  gd->keyidx, gd->tx, key_rsc, gd->key_rsc_len,
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  _gtk, gd->gtk_len) < 0) {
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: Failed to set GTK to "
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"the driver (alg=%d keylen=%d keyidx=%d)",
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			gd->alg, gd->gtk_len, gd->keyidx);
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_gtk_tx_bit_workaround(const struct wpa_sm *sm,
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						int tx)
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tx && sm->pairwise_cipher != WPA_CIPHER_NONE) {
6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Ignore Tx bit for GTK if a pairwise key is used. One AP
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * seemed to set this bit (incorrectly, since Tx is only when
6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * doing Group Key only APs) and without this workaround, the
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * data connection does not work because wpa_supplicant
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * configured non-zero keyidx to be used for unicast. */
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: Tx bit set for GTK, but pairwise "
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"keys are used - ignore Tx bit");
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return tx;
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_pairwise_gtk(struct wpa_sm *sm,
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       const struct wpa_eapol_key *key,
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       const u8 *gtk, size_t gtk_len,
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       int key_info)
6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_gtk_data gd;
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * IEEE Std 802.11i-2004 - 8.5.2 EAPOL-Key frames - Figure 43x
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * GTK KDE format:
6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * KeyID[bits 0-1], Tx [bit 2], Reserved [bits 3-7]
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Reserved [bits 0-7]
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * GTK
6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&gd, 0, sizeof(gd));
6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_key(MSG_DEBUG, "RSN: received GTK in pairwise handshake",
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			gtk, gtk_len);
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (gtk_len < 2 || gtk_len - 2 > sizeof(gd.gtk))
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gd.keyidx = gtk[0] & 0x3;
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gd.tx = wpa_supplicant_gtk_tx_bit_workaround(sm,
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						     !!(gtk[0] & BIT(2)));
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gtk += 2;
6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gtk_len -= 2;
6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(gd.gtk, gtk, gtk_len);
6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gd.gtk_len = gtk_len;
6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_supplicant_check_group_cipher(sm, sm->group_cipher,
6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      gtk_len, gtk_len,
6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      &gd.key_rsc_len, &gd.alg) ||
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wpa_supplicant_install_gtk(sm, &gd, key->key_rsc)) {
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"RSN: Failed to install GTK");
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_key_neg_complete(sm, sm->bssid,
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					key_info & WPA_KEY_INFO_SECURE);
7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ieee80211w_set_keys(struct wpa_sm *sm,
7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       struct wpa_eapol_ie_parse *ie)
7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W
7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC)
7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie->igtk) {
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		const struct wpa_igtk_kde *igtk;
7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		u16 keyidx;
7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ie->igtk_len != sizeof(*igtk))
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		igtk = (const struct wpa_igtk_kde *) ie->igtk;
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		keyidx = WPA_GET_LE16(igtk->keyid);
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: IGTK keyid %d "
7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"pn %02x%02x%02x%02x%02x%02x",
7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			keyidx, MAC2STR(igtk->pn));
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump_key(MSG_DEBUG, "WPA: IGTK",
7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				igtk->igtk, WPA_IGTK_LEN);
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (keyidx > 4095) {
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Invalid IGTK KeyID %d", keyidx);
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_sm_set_key(sm, WPA_ALG_IGTK, broadcast_ether_addr,
7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   keyidx, 0, igtk->pn, sizeof(igtk->pn),
7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   igtk->igtk, WPA_IGTK_LEN) < 0) {
7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Failed to configure IGTK to the driver");
7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_IEEE80211W */
7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */
7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_report_ie_mismatch(struct wpa_sm *sm,
7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   const char *reason, const u8 *src_addr,
7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   const u8 *wpa_ie, size_t wpa_ie_len,
7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   const u8 *rsn_ie, size_t rsn_ie_len)
7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: %s (src=" MACSTR ")",
7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		reason, MAC2STR(src_addr));
7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->ap_wpa_ie) {
7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_INFO, "WPA: WPA IE in Beacon/ProbeResp",
7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    sm->ap_wpa_ie, sm->ap_wpa_ie_len);
7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_ie) {
7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!sm->ap_wpa_ie) {
7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: No WPA IE in Beacon/ProbeResp");
7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_INFO, "WPA: WPA IE in 3/4 msg",
7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    wpa_ie, wpa_ie_len);
7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->ap_rsn_ie) {
7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_INFO, "WPA: RSN IE in Beacon/ProbeResp",
7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    sm->ap_rsn_ie, sm->ap_rsn_ie_len);
7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (rsn_ie) {
7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!sm->ap_rsn_ie) {
7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: No RSN IE in Beacon/ProbeResp");
7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_INFO, "WPA: RSN IE in 3/4 msg",
7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    rsn_ie, rsn_ie_len);
7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
780d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	wpa_sm_deauthenticate(sm, WLAN_REASON_IE_IN_4WAY_DIFFERS);
7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ft_validate_mdie(struct wpa_sm *sm,
7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    const unsigned char *src_addr,
7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    struct wpa_eapol_ie_parse *ie,
7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    const u8 *assoc_resp_mdie)
7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct rsn_mdie *mdie;
7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	mdie = (struct rsn_mdie *) (ie->mdie + 2);
7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie->mdie == NULL || ie->mdie_len < 2 + sizeof(*mdie) ||
7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(mdie->mobility_domain, sm->mobility_domain,
7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      MOBILITY_DOMAIN_ID_LEN) != 0) {
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: MDIE in msg 3/4 did "
7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"not match with the current mobility domain");
7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (assoc_resp_mdie &&
8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (assoc_resp_mdie[1] != ie->mdie[1] ||
8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     os_memcmp(assoc_resp_mdie, ie->mdie, 2 + ie->mdie[1]) != 0)) {
8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: MDIE mismatch");
8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "FT: MDIE in EAPOL-Key msg 3/4",
8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    ie->mdie, 2 + ie->mdie[1]);
8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "FT: MDIE in (Re)Association Response",
8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    assoc_resp_mdie, 2 + assoc_resp_mdie[1]);
8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ft_validate_ftie(struct wpa_sm *sm,
8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    const unsigned char *src_addr,
8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    struct wpa_eapol_ie_parse *ie,
8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    const u8 *assoc_resp_ftie)
8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie->ftie == NULL) {
8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"FT: No FTIE in EAPOL-Key msg 3/4");
8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (assoc_resp_ftie == NULL)
8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (assoc_resp_ftie[1] != ie->ftie[1] ||
8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(assoc_resp_ftie, ie->ftie, 2 + ie->ftie[1]) != 0) {
8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: FTIE mismatch");
8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "FT: FTIE in EAPOL-Key msg 3/4",
8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    ie->ftie, 2 + ie->ftie[1]);
8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "FT: FTIE in (Re)Association Response",
8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    assoc_resp_ftie, 2 + assoc_resp_ftie[1]);
8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ft_validate_rsnie(struct wpa_sm *sm,
8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     const unsigned char *src_addr,
8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     struct wpa_eapol_ie_parse *ie)
8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ie_data rsn;
8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!ie->rsn_ie)
8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Verify that PMKR1Name from EAPOL-Key message 3/4
8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * matches with the value we derived.
8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_parse_wpa_ie_rsn(ie->rsn_ie, ie->rsn_ie_len, &rsn) < 0 ||
8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    rsn.num_pmkid != 1 || rsn.pmkid == NULL) {
8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: No PMKR1Name in "
8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"FT 4-way handshake message 3/4");
8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(rsn.pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN) != 0) {
8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"FT: PMKR1Name mismatch in "
8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"FT 4-way handshake message 3/4");
8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from Authenticator",
8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    rsn.pmkid, WPA_PMK_NAME_LEN);
8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "FT: Derived PMKR1Name",
8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    sm->pmk_r1_name, WPA_PMK_NAME_LEN);
8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_validate_ie_ft(struct wpa_sm *sm,
8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 const unsigned char *src_addr,
8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 struct wpa_eapol_ie_parse *ie)
8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos, *end, *mdie = NULL, *ftie = NULL;
8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->assoc_resp_ies) {
8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = sm->assoc_resp_ies;
8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		end = pos + sm->assoc_resp_ies_len;
8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (pos + 2 < end) {
8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (pos + 2 + pos[1] > end)
8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			switch (*pos) {
8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			case WLAN_EID_MOBILITY_DOMAIN:
8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				mdie = pos;
8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			case WLAN_EID_FAST_BSS_TRANSITION:
8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				ftie = pos;
8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos += 2 + pos[1];
9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ft_validate_mdie(sm, src_addr, ie, mdie) < 0 ||
9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ft_validate_ftie(sm, src_addr, ie, ftie) < 0 ||
9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ft_validate_rsnie(sm, src_addr, ie) < 0)
9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_validate_ie(struct wpa_sm *sm,
9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const unsigned char *src_addr,
9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      struct wpa_eapol_ie_parse *ie)
9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->ap_wpa_ie == NULL && sm->ap_rsn_ie == NULL) {
9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: No WPA/RSN IE for this AP known. "
9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Trying to get from scan results");
9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_sm_get_beacon_ie(sm) < 0) {
9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Could not find AP from "
9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"the scan results");
9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG,
9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Found the current AP from "
9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"updated scan results");
9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie->wpa_ie == NULL && ie->rsn_ie == NULL &&
9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (sm->ap_wpa_ie || sm->ap_rsn_ie)) {
9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_report_ie_mismatch(sm, "IE in 3/4 msg does not match "
9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       "with IE in Beacon/ProbeResp (no IE?)",
9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       src_addr, ie->wpa_ie, ie->wpa_ie_len,
9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       ie->rsn_ie, ie->rsn_ie_len);
9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((ie->wpa_ie && sm->ap_wpa_ie &&
9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     (ie->wpa_ie_len != sm->ap_wpa_ie_len ||
9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	      os_memcmp(ie->wpa_ie, sm->ap_wpa_ie, ie->wpa_ie_len) != 0)) ||
9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (ie->rsn_ie && sm->ap_rsn_ie &&
9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     wpa_compare_rsn_ie(wpa_key_mgmt_ft(sm->key_mgmt),
9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				sm->ap_rsn_ie, sm->ap_rsn_ie_len,
9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				ie->rsn_ie, ie->rsn_ie_len))) {
9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_report_ie_mismatch(sm, "IE in 3/4 msg does not match "
9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       "with IE in Beacon/ProbeResp",
9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       src_addr, ie->wpa_ie, ie->wpa_ie_len,
9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       ie->rsn_ie, ie->rsn_ie_len);
9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->proto == WPA_PROTO_WPA &&
9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ie->rsn_ie && sm->ap_rsn_ie == NULL && sm->rsn_enabled) {
9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_report_ie_mismatch(sm, "Possible downgrade attack "
9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       "detected - RSN was enabled and RSN IE "
9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       "was in msg 3/4, but not in "
9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       "Beacon/ProbeResp",
9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       src_addr, ie->wpa_ie, ie->wpa_ie_len,
9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       ie->rsn_ie, ie->rsn_ie_len);
9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_key_mgmt_ft(sm->key_mgmt) &&
9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wpa_supplicant_validate_ie_ft(sm, src_addr, ie) < 0)
9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_supplicant_send_4_of_4 - Send message 4 of WPA/RSN 4-Way Handshake
9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @dst: Destination address for the frame
9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @key: Pointer to the EAPOL-Key frame header
9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ver: Version bits from EAPOL-Key Key Info
9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @key_info: Key Info
9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @kde: KDEs to include the EAPOL-Key frame
9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @kde_len: Length of KDEs
9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ptk: PTK to use for keyed hash and encryption
9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst,
9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       const struct wpa_eapol_key *key,
9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       u16 ver, u16 key_info,
9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       const u8 *kde, size_t kde_len,
9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       struct wpa_ptk *ptk)
9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t rlen;
9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_eapol_key *reply;
9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *rbuf;
9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (kde)
10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "WPA: KDE for msg 4/4", kde, kde_len);
10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  sizeof(*reply) + kde_len,
10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  &rlen, (void *) &reply);
10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (rbuf == NULL)
10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	reply->type = sm->proto == WPA_PROTO_RSN ?
10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key_info &= WPA_KEY_INFO_SECURE;
10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key_info |= ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_MIC;
10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE16(reply->key_info, key_info);
10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->proto == WPA_PROTO_RSN)
10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		WPA_PUT_BE16(reply->key_length, 0);
10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(reply->key_length, key->key_length, 2);
10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(reply->replay_counter, key->replay_counter,
10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  WPA_REPLAY_COUNTER_LEN);
10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE16(reply->key_data_length, kde_len);
10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (kde)
10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(reply + 1, kde, kde_len);
10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 4/4");
10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_eapol_key_send(sm, ptk->kck, ver, dst, ETH_P_EAPOL,
10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   rbuf, rlen, reply->key_mic);
10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_process_3_of_4(struct wpa_sm *sm,
10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  const struct wpa_eapol_key *key,
10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  u16 ver)
10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u16 key_info, keylen, len;
10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos;
10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_eapol_ie_parse ie;
10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE);
10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: RX message 3 of 4-Way "
10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"Handshake from " MACSTR " (ver=%d)", MAC2STR(sm->bssid), ver);
10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key_info = WPA_GET_BE16(key->key_info);
10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = (const u8 *) (key + 1);
10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = WPA_GET_BE16(key->key_data_length);
10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "WPA: IE KeyData", pos, len);
10501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (wpa_supplicant_parse_ies(pos, len, &ie) < 0)
10511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		goto failed;
10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: GTK IE in unencrypted key data");
10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W
10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie.igtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: IGTK KDE in unencrypted key data");
10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie.igtk && ie.igtk_len != sizeof(struct wpa_igtk_kde)) {
10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: Invalid IGTK KDE length %lu",
10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			(unsigned long) ie.igtk_len);
10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */
10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_supplicant_validate_ie(sm, sm->bssid, &ie) < 0)
10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(sm->anonce, key->key_nonce, WPA_NONCE_LEN) != 0) {
10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: ANonce from message 1 of 4-Way Handshake "
10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"differs from 3 of 4-Way Handshake - drop packet (src="
10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MACSTR ")", MAC2STR(sm->bssid));
10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	keylen = WPA_GET_BE16(key->key_length);
10844530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (keylen != wpa_cipher_key_len(sm->pairwise_cipher)) {
10854530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
10864530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			"WPA: Invalid %s key length %d (src=" MACSTR
10874530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			")", wpa_cipher_txt(sm->pairwise_cipher), keylen,
10884530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			MAC2STR(sm->bssid));
10894530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		goto failed;
10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_supplicant_send_4_of_4(sm, sm->bssid, key, ver, key_info,
10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       NULL, 0, &sm->ptk)) {
10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* SNonce was successfully used in msg 3/4, so mark it to be renewed
10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * for the next 4-Way Handshake. If msg 3 is received again, the old
10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * SNonce will still be used to avoid changing PTK. */
11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->renew_snonce = 1;
11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (key_info & WPA_KEY_INFO_INSTALL) {
11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_supplicant_install_ptk(sm, key))
11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto failed;
11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (key_info & WPA_KEY_INFO_SECURE) {
11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_sm_mlme_setprotection(
11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm, sm->bssid, MLME_SETPROTECTION_PROTECT_TYPE_RX,
11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eapol_sm_notify_portValid(sm->eapol, TRUE);
11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE);
11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie.gtk &&
11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wpa_supplicant_pairwise_gtk(sm, key,
11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					ie.gtk, ie.gtk_len, key_info) < 0) {
11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"RSN: Failed to configure GTK");
11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ieee80211w_set_keys(sm, &ie) < 0) {
11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"RSN: Failed to configure IGTK");
11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1129cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	if (ie.gtk)
1130cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		wpa_sm_set_rekey_offload(sm);
11311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return;
11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfailed:
11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_process_1_of_2_rsn(struct wpa_sm *sm,
11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     const u8 *keydata,
11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     size_t keydatalen,
11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     u16 key_info,
11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     struct wpa_gtk_data *gd)
11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int maxkeylen;
11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_eapol_ie_parse ie;
11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "RSN: msg 1/2 key data", keydata, keydatalen);
11491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (wpa_supplicant_parse_ies(keydata, keydatalen, &ie) < 0)
11501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return -1;
11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: GTK IE in unencrypted key data");
11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie.gtk == NULL) {
11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: No GTK IE in Group Key msg 1/2");
11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	maxkeylen = gd->gtk_len = ie.gtk_len - 2;
11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_supplicant_check_group_cipher(sm, sm->group_cipher,
11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      gd->gtk_len, maxkeylen,
11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      &gd->key_rsc_len, &gd->alg))
11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "RSN: received GTK in group key handshake",
11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    ie.gtk, ie.gtk_len);
11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gd->keyidx = ie.gtk[0] & 0x3;
11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gd->tx = wpa_supplicant_gtk_tx_bit_workaround(sm,
11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						      !!(ie.gtk[0] & BIT(2)));
11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie.gtk_len - 2 > sizeof(gd->gtk)) {
11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"RSN: Too long GTK in GTK IE (len=%lu)",
11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			(unsigned long) ie.gtk_len - 2);
11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(gd->gtk, ie.gtk + 2, ie.gtk_len - 2);
11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ieee80211w_set_keys(sm, &ie) < 0)
11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"RSN: Failed to configure IGTK");
11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_process_1_of_2_wpa(struct wpa_sm *sm,
11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     const struct wpa_eapol_key *key,
11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     size_t keydatalen, int key_info,
11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     size_t extra_len, u16 ver,
11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     struct wpa_gtk_data *gd)
11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t maxkeylen;
11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 ek[32];
11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gd->gtk_len = WPA_GET_BE16(key->key_length);
11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	maxkeylen = keydatalen;
12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (keydatalen > extra_len) {
12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: Truncated EAPOL-Key packet: "
12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"key_data_length=%lu > extra_len=%lu",
12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			(unsigned long) keydatalen, (unsigned long) extra_len);
12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (maxkeylen < 8) {
12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Too short maxkeylen (%lu)",
12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				(unsigned long) maxkeylen);
12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		maxkeylen -= 8;
12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_supplicant_check_group_cipher(sm, sm->group_cipher,
12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      gd->gtk_len, maxkeylen,
12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      &gd->key_rsc_len, &gd->alg))
12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gd->keyidx = (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >>
12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		WPA_KEY_INFO_KEY_INDEX_SHIFT;
12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4) {
12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(ek, key->key_iv, 16);
12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(ek + 16, sm->ptk.kek, 16);
12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (keydatalen > sizeof(gd->gtk)) {
12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: RC4 key data too long (%lu)",
12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				(unsigned long) keydatalen);
12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(gd->gtk, key + 1, keydatalen);
12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (rc4_skip(ek, 32, 256, gd->gtk, keydatalen)) {
12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: RC4 failed");
12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (keydatalen % 8) {
12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Unsupported AES-WRAP len %lu",
12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				(unsigned long) keydatalen);
12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (maxkeylen > sizeof(gd->gtk)) {
12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: AES-WRAP key data "
12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"too long (keydatalen=%lu maxkeylen=%lu)",
12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				(unsigned long) keydatalen,
12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				(unsigned long) maxkeylen);
12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (aes_unwrap(sm->ptk.kek, maxkeylen / 8,
12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       (const u8 *) (key + 1), gd->gtk)) {
12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: AES unwrap failed - could not decrypt "
12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"GTK");
12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: Unsupported key_info type %d", ver);
12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gd->tx = wpa_supplicant_gtk_tx_bit_workaround(
12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm, !!(key_info & WPA_KEY_INFO_TXRX));
12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_send_2_of_2(struct wpa_sm *sm,
12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const struct wpa_eapol_key *key,
12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      int ver, u16 key_info)
12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t rlen;
12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_eapol_key *reply;
12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *rbuf;
12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  sizeof(*reply), &rlen, (void *) &reply);
12828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (rbuf == NULL)
12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	reply->type = sm->proto == WPA_PROTO_RSN ?
12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key_info &= WPA_KEY_INFO_KEY_INDEX_MASK;
12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key_info |= ver | WPA_KEY_INFO_MIC | WPA_KEY_INFO_SECURE;
12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE16(reply->key_info, key_info);
12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->proto == WPA_PROTO_RSN)
12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		WPA_PUT_BE16(reply->key_length, 0);
12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(reply->key_length, key->key_length, 2);
12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(reply->replay_counter, key->replay_counter,
12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  WPA_REPLAY_COUNTER_LEN);
12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE16(reply->key_data_length, 0);
12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 2/2");
13008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_eapol_key_send(sm, sm->ptk.kck, ver, sm->bssid, ETH_P_EAPOL,
13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   rbuf, rlen, reply->key_mic);
13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_process_1_of_2(struct wpa_sm *sm,
13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  const unsigned char *src_addr,
13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  const struct wpa_eapol_key *key,
13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  int extra_len, u16 ver)
13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u16 key_info, keydatalen;
13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int rekey, ret;
13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_gtk_data gd;
13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&gd, 0, sizeof(gd));
13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rekey = wpa_sm_get_state(sm) == WPA_COMPLETED;
13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: RX message 1 of Group Key "
13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"Handshake from " MACSTR " (ver=%d)", MAC2STR(src_addr), ver);
13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key_info = WPA_GET_BE16(key->key_info);
13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	keydatalen = WPA_GET_BE16(key->key_data_length);
13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->proto == WPA_PROTO_RSN) {
13268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = wpa_supplicant_process_1_of_2_rsn(sm,
13278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							(const u8 *) (key + 1),
13288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							keydatalen, key_info,
13298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							&gd);
13308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = wpa_supplicant_process_1_of_2_wpa(sm, key, keydatalen,
13328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							key_info, extra_len,
13338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							ver, &gd);
13348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE);
13378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret)
13398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_supplicant_install_gtk(sm, &gd, key->key_rsc) ||
13428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wpa_supplicant_send_2_of_2(sm, key, ver, key_info))
13438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
13448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (rekey) {
13468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Group rekeying "
13478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"completed with " MACSTR " [GTK=%s]",
13488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(sm->bssid), wpa_cipher_txt(sm->group_cipher));
13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_sm_cancel_auth_timeout(sm);
13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_sm_set_state(sm, WPA_COMPLETED);
13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
13528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_key_neg_complete(sm, sm->bssid,
13538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						key_info &
13548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						WPA_KEY_INFO_SECURE);
13558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1356cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt
1357cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	wpa_sm_set_rekey_offload(sm);
1358cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt
13598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return;
13608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfailed:
13628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
13638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_verify_eapol_key_mic(struct wpa_sm *sm,
13678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       struct wpa_eapol_key *key,
13688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       u16 ver,
13698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       const u8 *buf, size_t len)
13708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 mic[16];
13728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ok = 0;
13738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(mic, key->key_mic, 16);
13758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->tptk_set) {
13768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(key->key_mic, 0, 16);
13778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_eapol_key_mic(sm->tptk.kck, ver, buf, len,
13788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  key->key_mic);
13798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(mic, key->key_mic, 16) != 0) {
13808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
13818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Invalid EAPOL-Key MIC "
13828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"when using TPTK - ignoring TPTK");
13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
13848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ok = 1;
13858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->tptk_set = 0;
13868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->ptk_set = 1;
13878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(&sm->ptk, &sm->tptk, sizeof(sm->ptk));
13888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
13898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!ok && sm->ptk_set) {
13928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(key->key_mic, 0, 16);
13938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_eapol_key_mic(sm->ptk.kck, ver, buf, len,
13948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  key->key_mic);
13958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(mic, key->key_mic, 16) != 0) {
13968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
13978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Invalid EAPOL-Key MIC - "
13988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"dropping packet");
13998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
14008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
14018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ok = 1;
14028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!ok) {
14058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
14068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: Could not verify EAPOL-Key MIC - "
14078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"dropping packet");
14088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
14098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(sm->rx_replay_counter, key->replay_counter,
14128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  WPA_REPLAY_COUNTER_LEN);
14138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->rx_replay_counter_set = 1;
14148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
14158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
14168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Decrypt RSN EAPOL-Key key data (RC4 or AES-WRAP) */
14198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm,
14208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   struct wpa_eapol_key *key, u16 ver)
14218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
14228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u16 keydatalen = WPA_GET_BE16(key->key_data_length);
14238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "RSN: encrypted key data",
14258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    (u8 *) (key + 1), keydatalen);
14268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!sm->ptk_set) {
14278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
14288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: PTK not available, cannot decrypt EAPOL-Key Key "
14298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Data");
14308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
14318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Decrypt key data here so that this operation does not need
14348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * to be implemented separately for each message type. */
14358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4) {
14368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		u8 ek[32];
14378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(ek, key->key_iv, 16);
14388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(ek + 16, sm->ptk.kek, 16);
14398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (rc4_skip(ek, 32, 256, (u8 *) (key + 1), keydatalen)) {
14408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
14418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: RC4 failed");
14428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
14438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
14448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
14458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   ver == WPA_KEY_INFO_TYPE_AES_128_CMAC) {
14468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		u8 *buf;
14478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (keydatalen % 8) {
14488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
14498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Unsupported AES-WRAP len %d",
14508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				keydatalen);
14518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
14528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
14538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		keydatalen -= 8; /* AES-WRAP adds 8 bytes */
14548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		buf = os_malloc(keydatalen);
14558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (buf == NULL) {
14568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
14578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: No memory for AES-UNWRAP buffer");
14588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
14598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
14608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (aes_unwrap(sm->ptk.kek, keydatalen / 8,
14618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       (u8 *) (key + 1), buf)) {
14628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(buf);
14638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
14648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: AES unwrap failed - "
14658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"could not decrypt EAPOL-Key key data");
14668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
14678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
14688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(key + 1, buf, keydatalen);
14698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(buf);
14708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		WPA_PUT_BE16(key->key_data_length, keydatalen);
14718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
14728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
14738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: Unsupported key_info type %d", ver);
14748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
14758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_key(MSG_DEBUG, "WPA: decrypted EAPOL-Key key data",
14778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			(u8 *) (key + 1), keydatalen);
14788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
14798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
14808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
14838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_aborted_cached - Notify WPA that PMKSA caching was aborted
14848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
14858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
14868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_aborted_cached(struct wpa_sm *sm)
14878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
14888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm && sm->cur_pmksa) {
14898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
14908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"RSN: Cancelling PMKSA caching attempt");
14918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->cur_pmksa = NULL;
14928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
14948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_eapol_key_dump(struct wpa_sm *sm,
14978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       const struct wpa_eapol_key *key)
14988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
14998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_STDOUT_DEBUG
15008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u16 key_info = WPA_GET_BE16(key->key_info);
15018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "  EAPOL-Key type=%d", key->type);
15038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
15048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"  key_info 0x%x (ver=%d keyidx=%d rsvd=%d %s%s%s%s%s%s%s%s)",
15058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_info, key_info & WPA_KEY_INFO_TYPE_MASK,
15068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		(key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >>
15078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		WPA_KEY_INFO_KEY_INDEX_SHIFT,
15088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		(key_info & (BIT(13) | BIT(14) | BIT(15))) >> 13,
15098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_info & WPA_KEY_INFO_KEY_TYPE ? "Pairwise" : "Group",
15108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_info & WPA_KEY_INFO_INSTALL ? " Install" : "",
15118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_info & WPA_KEY_INFO_ACK ? " Ack" : "",
15128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_info & WPA_KEY_INFO_MIC ? " MIC" : "",
15138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_info & WPA_KEY_INFO_SECURE ? " Secure" : "",
15148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_info & WPA_KEY_INFO_ERROR ? " Error" : "",
15158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_info & WPA_KEY_INFO_REQUEST ? " Request" : "",
15168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_info & WPA_KEY_INFO_ENCR_KEY_DATA ? " Encr" : "");
15178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
15188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"  key_length=%u key_data_length=%u",
15198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		WPA_GET_BE16(key->key_length),
15208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		WPA_GET_BE16(key->key_data_length));
15218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "  replay_counter",
15228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    key->replay_counter, WPA_REPLAY_COUNTER_LEN);
15238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "  key_nonce", key->key_nonce, WPA_NONCE_LEN);
15248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "  key_iv", key->key_iv, 16);
15258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "  key_rsc", key->key_rsc, 8);
15268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "  key_id (reserved)", key->key_id, 8);
15278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "  key_mic", key->key_mic, 16);
15288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_STDOUT_DEBUG */
15298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
15338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_rx_eapol - Process received WPA EAPOL frames
15348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
15358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @src_addr: Source MAC address of the EAPOL packet
15368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Pointer to the beginning of the EAPOL data (EAPOL header)
15378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Length of the EAPOL frame
15388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 1 = WPA EAPOL-Key processed, 0 = not a WPA EAPOL-Key, -1 failure
15398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
15408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called for each received EAPOL frame. Other than EAPOL-Key
15418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * frames can be skipped if filtering is done elsewhere. wpa_sm_rx_eapol() is
15428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * only processing WPA and WPA2 EAPOL-Key frames.
15438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
15448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * The received EAPOL-Key packets are validated and valid packets are replied
15458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to. In addition, key material (PTK, GTK) is configured at the end of a
15468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * successful key handshake.
15478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
15488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
15498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    const u8 *buf, size_t len)
15508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t plen, data_len, extra_len;
15528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct ieee802_1x_hdr *hdr;
15538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_eapol_key *key;
15548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u16 key_info, ver;
15558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *tmp;
15568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret = -1;
15578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_peerkey *peerkey = NULL;
15588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
15608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->ft_completed = 0;
15618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
15628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < sizeof(*hdr) + sizeof(*key)) {
15648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
15658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: EAPOL frame too short to be a WPA "
15668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"EAPOL-Key (len %lu, expecting at least %lu)",
15678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			(unsigned long) len,
15688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			(unsigned long) sizeof(*hdr) + sizeof(*key));
15698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
15708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmp = os_malloc(len);
15738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmp == NULL)
15748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
15758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(tmp, buf, len);
15768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hdr = (struct ieee802_1x_hdr *) tmp;
15788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key = (struct wpa_eapol_key *) (hdr + 1);
15798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	plen = be_to_host16(hdr->length);
15808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data_len = plen + sizeof(*hdr);
15818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
15828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"IEEE 802.1X RX: version=%d type=%d length=%lu",
15838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hdr->version, hdr->type, (unsigned long) plen);
15848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hdr->version < EAPOL_VERSION) {
15868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* TODO: backwards compatibility */
15878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hdr->type != IEEE802_1X_TYPE_EAPOL_KEY) {
15898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
15908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: EAPOL frame (type %u) discarded, "
15918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"not a Key frame", hdr->type);
15928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = 0;
15938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
15948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (plen > len - sizeof(*hdr) || plen < sizeof(*key)) {
15968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
15978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: EAPOL frame payload size %lu "
15988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"invalid (frame size %lu)",
15998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			(unsigned long) plen, (unsigned long) len);
16008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = 0;
16018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
16028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (key->type != EAPOL_KEY_TYPE_WPA && key->type != EAPOL_KEY_TYPE_RSN)
16058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{
16068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
16078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: EAPOL-Key type (%d) unknown, discarded",
16088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			key->type);
16098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = 0;
16108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
16118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_eapol_key_dump(sm, key);
16138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_sm_notify_lower_layer_success(sm->eapol, 0);
16158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL-Key", tmp, len);
16168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data_len < len) {
16178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
16188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: ignoring %lu bytes after the IEEE 802.1X data",
16198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			(unsigned long) len - data_len);
16208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key_info = WPA_GET_BE16(key->key_info);
16228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ver = key_info & WPA_KEY_INFO_TYPE_MASK;
16238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ver != WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 &&
16248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W)
16258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ver != WPA_KEY_INFO_TYPE_AES_128_CMAC &&
16268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */
16278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
16288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
16298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: Unsupported EAPOL-Key descriptor version %d",
16308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ver);
16318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
16328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
16358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_key_mgmt_ft(sm->key_mgmt)) {
16368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* IEEE 802.11r uses a new key_info type (AES-128-CMAC). */
16378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) {
16388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
16398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"FT: AP did not use AES-128-CMAC");
16408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto out;
16418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
16428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
16438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
16448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W
16458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_key_mgmt_sha256(sm->key_mgmt)) {
16468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) {
16478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
16488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: AP did not use the "
16498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"negotiated AES-128-CMAC");
16508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto out;
16518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
16528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
16538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */
16548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->pairwise_cipher == WPA_CIPHER_CCMP &&
16558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
16568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
16578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: CCMP is used, but EAPOL-Key "
16588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"descriptor version (%d) is not 2", ver);
16598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->group_cipher != WPA_CIPHER_CCMP &&
16608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    !(key_info & WPA_KEY_INFO_KEY_TYPE)) {
16618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/* Earlier versions of IEEE 802.11i did not explicitly
16628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * require version 2 descriptor for all EAPOL-Key
16638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * packets, so allow group keys to use version 1 if
16648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * CCMP is not used for them. */
16658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
16668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Backwards compatibility: allow invalid "
16678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"version for non-CCMP group keys");
16688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else
16698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto out;
16708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
167161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (sm->pairwise_cipher == WPA_CIPHER_GCMP &&
167261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	    ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
167361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
167461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			"WPA: GCMP is used, but EAPOL-Key "
167561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			"descriptor version (%d) is not 2", ver);
167661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		goto out;
167761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
16788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_PEERKEY
16808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) {
16818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(peerkey->addr, src_addr, ETH_ALEN) == 0)
16828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
16838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!(key_info & WPA_KEY_INFO_SMK_MESSAGE) && peerkey) {
16868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!peerkey->initiator && peerkey->replay_counter_set &&
16878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    os_memcmp(key->replay_counter, peerkey->replay_counter,
16888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      WPA_REPLAY_COUNTER_LEN) <= 0) {
16898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
16908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"RSN: EAPOL-Key Replay Counter did not "
16918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"increase (STK) - dropping packet");
16928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto out;
16938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (peerkey->initiator) {
16948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u8 _tmp[WPA_REPLAY_COUNTER_LEN];
16958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(_tmp, key->replay_counter,
16968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  WPA_REPLAY_COUNTER_LEN);
16978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			inc_byte_array(_tmp, WPA_REPLAY_COUNTER_LEN);
16988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (os_memcmp(_tmp, peerkey->replay_counter,
16998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      WPA_REPLAY_COUNTER_LEN) != 0) {
17008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
17018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"RSN: EAPOL-Key Replay "
17028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"Counter did not match (STK) - "
17038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"dropping packet");
17048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				goto out;
17058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
17068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
17078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (peerkey && peerkey->initiator && (key_info & WPA_KEY_INFO_ACK)) {
17108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
17118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"RSN: Ack bit in key_info from STK peer");
17128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
17138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_PEERKEY */
17158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!peerkey && sm->rx_replay_counter_set &&
17178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(key->replay_counter, sm->rx_replay_counter,
17188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      WPA_REPLAY_COUNTER_LEN) <= 0) {
17198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
17208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: EAPOL-Key Replay Counter did not increase - "
17218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"dropping packet");
17228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
17238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!(key_info & (WPA_KEY_INFO_ACK | WPA_KEY_INFO_SMK_MESSAGE))
17268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_PEERKEY
17278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    && (peerkey == NULL || !peerkey->initiator)
17288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_PEERKEY */
17298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		) {
17308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
17318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: No Ack bit in key_info");
17328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
17338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (key_info & WPA_KEY_INFO_REQUEST) {
17368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
17378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: EAPOL-Key with Request bit - dropped");
17388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
17398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((key_info & WPA_KEY_INFO_MIC) && !peerkey &&
17428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wpa_supplicant_verify_eapol_key_mic(sm, key, ver, tmp, data_len))
17438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
17448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_PEERKEY
17468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((key_info & WPA_KEY_INFO_MIC) && peerkey &&
17478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    peerkey_verify_eapol_key_mic(sm, peerkey, key, ver, tmp, data_len))
17488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
17498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_PEERKEY */
17508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	extra_len = data_len - sizeof(*hdr) - sizeof(*key);
17528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (WPA_GET_BE16(key->key_data_length) > extra_len) {
17548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Invalid EAPOL-Key "
17558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"frame - key_data overflow (%d > %lu)",
17568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			WPA_GET_BE16(key->key_data_length),
17578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			(unsigned long) extra_len);
17588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
17598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	extra_len = WPA_GET_BE16(key->key_data_length);
17618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->proto == WPA_PROTO_RSN &&
17638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
17648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_supplicant_decrypt_key_data(sm, key, ver))
17658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto out;
17668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		extra_len = WPA_GET_BE16(key->key_data_length);
17678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (key_info & WPA_KEY_INFO_KEY_TYPE) {
17708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) {
17718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
17728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Ignored EAPOL-Key (Pairwise) with "
17738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"non-zero key index");
17748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto out;
17758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
17768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (peerkey) {
17778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/* PeerKey 4-Way Handshake */
17788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			peerkey_rx_eapol_4way(sm, peerkey, key, key_info, ver);
17798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (key_info & WPA_KEY_INFO_MIC) {
17808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/* 3/4 4-Way Handshake */
17818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_supplicant_process_3_of_4(sm, key, ver);
17828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
17838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/* 1/4 4-Way Handshake */
17848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_supplicant_process_1_of_4(sm, src_addr, key,
17858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						      ver);
17868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
17878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (key_info & WPA_KEY_INFO_SMK_MESSAGE) {
17888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* PeerKey SMK Handshake */
17898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		peerkey_rx_eapol_smk(sm, src_addr, key, extra_len, key_info,
17908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     ver);
17918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
17928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (key_info & WPA_KEY_INFO_MIC) {
17938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/* 1/2 Group Key Handshake */
17948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_supplicant_process_1_of_2(sm, src_addr, key,
17958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						      extra_len, ver);
17968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
17978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
17988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: EAPOL-Key (Group) without Mic bit - "
17998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"dropped");
18008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
18018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = 1;
18048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtout:
18068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(tmp);
18078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
18088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_CTRL_IFACE
18128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u32 wpa_key_mgmt_suite(struct wpa_sm *sm)
18138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (sm->key_mgmt) {
18158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_KEY_MGMT_IEEE8021X:
18168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return (sm->proto == WPA_PROTO_RSN ?
18178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			RSN_AUTH_KEY_MGMT_UNSPEC_802_1X :
18188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			WPA_AUTH_KEY_MGMT_UNSPEC_802_1X);
18198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_KEY_MGMT_PSK:
18208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return (sm->proto == WPA_PROTO_RSN ?
18218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X :
18228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X);
18238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
18248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_KEY_MGMT_FT_IEEE8021X:
18258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return RSN_AUTH_KEY_MGMT_FT_802_1X;
18268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_KEY_MGMT_FT_PSK:
18278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return RSN_AUTH_KEY_MGMT_FT_PSK;
18288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
18298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W
18308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_KEY_MGMT_IEEE8021X_SHA256:
18318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return RSN_AUTH_KEY_MGMT_802_1X_SHA256;
18328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_KEY_MGMT_PSK_SHA256:
18338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return RSN_AUTH_KEY_MGMT_PSK_SHA256;
18348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */
1835d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	case WPA_KEY_MGMT_CCKM:
1836d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		return (sm->proto == WPA_PROTO_RSN ?
1837d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			RSN_AUTH_KEY_MGMT_CCKM:
1838d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			WPA_AUTH_KEY_MGMT_CCKM);
18398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_KEY_MGMT_WPA_NONE:
18408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return WPA_AUTH_KEY_MGMT_NONE;
18418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
18428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
18438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define RSN_SUITE "%02x-%02x-%02x-%d"
18488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define RSN_SUITE_ARG(s) \
18498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt((s) >> 24) & 0xff, ((s) >> 16) & 0xff, ((s) >> 8) & 0xff, (s) & 0xff
18508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
18528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_get_mib - Dump text list of MIB entries
18538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
18548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Buffer for the list
18558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buflen: Length of the buffer
18568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Number of bytes written to buffer
18578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
18588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used fetch dot11 MIB variables.
18598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
18608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen)
18618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char pmkid_txt[PMKID_LEN * 2 + 1];
18638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int rsna, ret;
18648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
18658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->cur_pmksa) {
18678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_snprintf_hex(pmkid_txt, sizeof(pmkid_txt),
18688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 sm->cur_pmksa->pmkid, PMKID_LEN);
18698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
18708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pmkid_txt[0] = '\0';
18718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((wpa_key_mgmt_wpa_psk(sm->key_mgmt) ||
18738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt)) &&
18748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    sm->proto == WPA_PROTO_RSN)
18758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		rsna = 1;
18768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
18778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		rsna = 0;
18788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = os_snprintf(buf, buflen,
18808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dot11RSNAOptionImplemented=TRUE\n"
18818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dot11RSNAPreauthenticationImplemented=TRUE\n"
18828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dot11RSNAEnabled=%s\n"
18838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dot11RSNAPreauthenticationEnabled=%s\n"
18848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dot11RSNAConfigVersion=%d\n"
18858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dot11RSNAConfigPairwiseKeysSupported=5\n"
18868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dot11RSNAConfigGroupCipherSize=%d\n"
18878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dot11RSNAConfigPMKLifetime=%d\n"
18888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dot11RSNAConfigPMKReauthThreshold=%d\n"
18898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dot11RSNAConfigNumberOfPTKSAReplayCounters=1\n"
18908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dot11RSNAConfigSATimeout=%d\n",
18918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  rsna ? "TRUE" : "FALSE",
18928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  rsna ? "TRUE" : "FALSE",
18938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  RSN_VERSION,
18944530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			  wpa_cipher_key_len(sm->group_cipher) * 8,
18958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sm->dot11RSNAConfigPMKLifetime,
18968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sm->dot11RSNAConfigPMKReauthThreshold,
18978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sm->dot11RSNAConfigSATimeout);
18988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret < 0 || (size_t) ret >= buflen)
18998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
19008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = ret;
19018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = os_snprintf(
19038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		buf + len, buflen - len,
19048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"dot11RSNAAuthenticationSuiteSelected=" RSN_SUITE "\n"
19058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"dot11RSNAPairwiseCipherSelected=" RSN_SUITE "\n"
19068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"dot11RSNAGroupCipherSelected=" RSN_SUITE "\n"
19078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"dot11RSNAPMKIDUsed=%s\n"
19088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"dot11RSNAAuthenticationSuiteRequested=" RSN_SUITE "\n"
19098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"dot11RSNAPairwiseCipherRequested=" RSN_SUITE "\n"
19108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"dot11RSNAGroupCipherRequested=" RSN_SUITE "\n"
19118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"dot11RSNAConfigNumberOfGTKSAReplayCounters=0\n"
19128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"dot11RSNA4WayHandshakeFailures=%u\n",
19138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		RSN_SUITE_ARG(wpa_key_mgmt_suite(sm)),
19144530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		RSN_SUITE_ARG(wpa_cipher_to_suite(sm->proto,
19154530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt						  sm->pairwise_cipher)),
19164530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		RSN_SUITE_ARG(wpa_cipher_to_suite(sm->proto,
19174530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt						  sm->group_cipher)),
19188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pmkid_txt,
19198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		RSN_SUITE_ARG(wpa_key_mgmt_suite(sm)),
19204530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		RSN_SUITE_ARG(wpa_cipher_to_suite(sm->proto,
19214530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt						  sm->pairwise_cipher)),
19224530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		RSN_SUITE_ARG(wpa_cipher_to_suite(sm->proto,
19234530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt						  sm->group_cipher)),
19248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->dot11RSNA4WayHandshakeFailures);
19258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret >= 0 && (size_t) ret < buflen)
19268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len += ret;
19278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return (int) len;
19298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE */
19318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_sm_pmksa_free_cb(struct rsn_pmksa_cache_entry *entry,
1934d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				 void *ctx, enum pmksa_free_reason reason)
19358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_sm *sm = ctx;
1937d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	int deauth = 0;
1938d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
1939d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: PMKSA cache entry free_cb: "
1940d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		MACSTR " reason=%d", MAC2STR(entry->aa), reason);
1941d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
1942d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (sm->cur_pmksa == entry) {
1943d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
1944d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			"RSN: %s current PMKSA entry",
1945d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			reason == PMKSA_REPLACE ? "replaced" : "removed");
1946d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		pmksa_cache_clear_current(sm);
1947d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
1948d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		/*
1949d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		 * If an entry is simply being replaced, there's no need to
1950d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		 * deauthenticate because it will be immediately re-added.
1951d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		 * This happens when EAP authentication is completed again
1952d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		 * (reauth or failed PMKSA caching attempt).
1953d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		 */
1954d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		if (reason != PMKSA_REPLACE)
1955d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			deauth = 1;
1956d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	}
19578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1958d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (reason == PMKSA_EXPIRE &&
19598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (sm->pmk_len == entry->pmk_len &&
19608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     os_memcmp(sm->pmk, entry->pmk, sm->pmk_len) == 0)) {
19618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
1962d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			"RSN: deauthenticating due to expired PMK");
1963d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		pmksa_cache_clear_current(sm);
1964d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		deauth = 1;
1965d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	}
19668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1967d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (deauth) {
19688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(sm->pmk, 0, sizeof(sm->pmk));
19698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
19708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
19758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_init - Initialize WPA state machine
19768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ctx: Context pointer for callbacks; this needs to be an allocated buffer
19778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the allocated WPA state machine data
19788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
19798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used to allocate a new WPA state machine and the returned
19808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * value is passed to all WPA state machine calls.
19818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
19828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_sm * wpa_sm_init(struct wpa_sm_ctx *ctx)
19838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_sm *sm;
19858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm = os_zalloc(sizeof(*sm));
19878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
19888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
19898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_init(&sm->pmksa_candidates);
19908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->renew_snonce = 1;
19918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->ctx = ctx;
19928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->dot11RSNAConfigPMKLifetime = 43200;
19948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->dot11RSNAConfigPMKReauthThreshold = 70;
19958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->dot11RSNAConfigSATimeout = 60;
19968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->pmksa = pmksa_cache_init(wpa_sm_pmksa_free_cb, sm, sm);
19988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->pmksa == NULL) {
19998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
20008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"RSN: PMKSA cache initialization failed");
20018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(sm);
20028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
20038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return sm;
20068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
20108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_deinit - Deinitialize WPA state machine
20118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
20128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
20138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_deinit(struct wpa_sm *sm)
20148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
20168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
20178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pmksa_cache_deinit(sm->pmksa);
20188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(wpa_sm_start_preauth, sm, NULL);
20198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL);
20208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sm->assoc_wpa_ie);
20218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sm->ap_wpa_ie);
20228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sm->ap_rsn_ie);
20238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sm->ctx);
20248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	peerkey_deinit(sm);
20258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
20268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sm->assoc_resp_ies);
20278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
20288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sm);
20298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
20338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_notify_assoc - Notify WPA state machine about association
20348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
20358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @bssid: The BSSID of the new association
20368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
20378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called to let WPA state machine know that the connection
20388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * was established.
20398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
20408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid)
20418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int clear_ptk = 1;
20438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
20458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
20468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
20488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"WPA: Association event - clear replay counter");
20498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(sm->bssid, bssid, ETH_ALEN);
20508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(sm->rx_replay_counter, 0, WPA_REPLAY_COUNTER_LEN);
20518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->rx_replay_counter_set = 0;
20528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->renew_snonce = 1;
20538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(sm->preauth_bssid, bssid, ETH_ALEN) == 0)
20548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		rsn_preauth_deinit(sm);
20558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
20578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_ft_is_completed(sm)) {
20588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
20598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Clear portValid to kick EAPOL state machine to re-enter
20608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * AUTHENTICATED state to get the EAPOL port Authorized.
20618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
20628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eapol_sm_notify_portValid(sm->eapol, FALSE);
20638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_key_neg_complete(sm, sm->bssid, 1);
20648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Prepare for the next transition */
20668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_ft_prepare_auth_request(sm, NULL);
20678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		clear_ptk = 0;
20698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
20718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (clear_ptk) {
20738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
20748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * IEEE 802.11, 8.4.10: Delete PTK SA on (re)association if
20758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * this is not part of a Fast BSS Transition.
20768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
20778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Clear old PTK");
20788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->ptk_set = 0;
20798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->tptk_set = 0;
20808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS
20838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_tdls_assoc(sm);
20848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS */
20858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
20898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_notify_disassoc - Notify WPA state machine about disassociation
20908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
20918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
20928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called to let WPA state machine know that the connection
20938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * was lost. This will abort any existing pre-authentication session.
20948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
20958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_notify_disassoc(struct wpa_sm *sm)
20968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rsn_preauth_deinit(sm);
2098d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	pmksa_cache_clear_current(sm);
20998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_sm_get_state(sm) == WPA_4WAY_HANDSHAKE)
21008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->dot11RSNA4WayHandshakeFailures++;
21018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS
21028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_tdls_disassoc(sm);
21038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS */
21048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
21088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_pmk - Set PMK
21098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
21108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pmk: The new PMK
21118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pmk_len: The length of the new PMK in bytes
21128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
21138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Configure the PMK for WPA state machine.
21148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
21158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len)
21168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
21188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
21198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->pmk_len = pmk_len;
21218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(sm->pmk, pmk, pmk_len);
21228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
21248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Set XXKey to be PSK for FT key derivation */
21258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->xxkey_len = pmk_len;
21268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(sm->xxkey, pmk, pmk_len);
21278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
21288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
21328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_pmk_from_pmksa - Set PMK based on the current PMKSA
21338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
21348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
21358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Take the PMK from the current PMKSA into use. If no PMKSA is active, the PMK
21368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * will be cleared.
21378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
21388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_set_pmk_from_pmksa(struct wpa_sm *sm)
21398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
21418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
21428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->cur_pmksa) {
21448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->pmk_len = sm->cur_pmksa->pmk_len;
21458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(sm->pmk, sm->cur_pmksa->pmk, sm->pmk_len);
21468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
21478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->pmk_len = PMK_LEN;
21488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(sm->pmk, 0, PMK_LEN);
21498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
21548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_fast_reauth - Set fast reauthentication (EAP) enabled/disabled
21558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
21568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @fast_reauth: Whether fast reauthentication (EAP) is allowed
21578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
21588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_set_fast_reauth(struct wpa_sm *sm, int fast_reauth)
21598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm)
21618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->fast_reauth = fast_reauth;
21628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
21668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_scard_ctx - Set context pointer for smartcard callbacks
21678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
21688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @scard_ctx: Context pointer for smartcard related callback functions
21698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
21708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_set_scard_ctx(struct wpa_sm *sm, void *scard_ctx)
21718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
21738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
21748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->scard_ctx = scard_ctx;
21758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->preauth_eapol)
21768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eapol_sm_register_scard_ctx(sm->preauth_eapol, scard_ctx);
21778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
21818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_config - Notification of current configration change
21828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
21838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @config: Pointer to current network configuration
21848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
21858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Notify WPA state machine that configuration has changed. config will be
21868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * stored as a backpointer to network configuration. This can be %NULL to clear
21878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the stored pointed.
21888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
21898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_set_config(struct wpa_sm *sm, struct rsn_supp_config *config)
21908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!sm)
21928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
21938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config) {
21958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->network_ctx = config->network_ctx;
21968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->peerkey_enabled = config->peerkey_enabled;
21978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->allowed_pairwise_cipher = config->allowed_pairwise_cipher;
21988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->proactive_key_caching = config->proactive_key_caching;
21998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eap_workaround = config->eap_workaround;
22008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eap_conf_ctx = config->eap_conf_ctx;
22018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (config->ssid) {
22028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(sm->ssid, config->ssid, config->ssid_len);
22038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->ssid_len = config->ssid_len;
22048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else
22058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->ssid_len = 0;
22068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->wpa_ptk_rekey = config->wpa_ptk_rekey;
22078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
22088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->network_ctx = NULL;
22098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->peerkey_enabled = 0;
22108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->allowed_pairwise_cipher = 0;
22118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->proactive_key_caching = 0;
22128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eap_workaround = 0;
22138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eap_conf_ctx = NULL;
22148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->ssid_len = 0;
22158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->wpa_ptk_rekey = 0;
22168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
22218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_own_addr - Set own MAC address
22228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
22238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: Own MAC address
22248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
22258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_set_own_addr(struct wpa_sm *sm, const u8 *addr)
22268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm)
22288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(sm->own_addr, addr, ETH_ALEN);
22298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
22338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_ifname - Set network interface name
22348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
22358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ifname: Interface name
22368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @bridge_ifname: Optional bridge interface name (for pre-auth)
22378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
22388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_set_ifname(struct wpa_sm *sm, const char *ifname,
22398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       const char *bridge_ifname)
22408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm) {
22428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->ifname = ifname;
22438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->bridge_ifname = bridge_ifname;
22448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
22498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_eapol - Set EAPOL state machine pointer
22508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
22518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @eapol: Pointer to EAPOL state machine allocated with eapol_sm_init()
22528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
22538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_set_eapol(struct wpa_sm *sm, struct eapol_sm *eapol)
22548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm)
22568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eapol = eapol;
22578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
22618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_param - Set WPA state machine parameters
22628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
22638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @param: Parameter field
22648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @value: Parameter value
22658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
22668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
22678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param,
22688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     unsigned int value)
22698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret = 0;
22718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
22738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
22748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (param) {
22768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case RSNA_PMK_LIFETIME:
22778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (value > 0)
22788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->dot11RSNAConfigPMKLifetime = value;
22798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
22808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = -1;
22818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
22828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case RSNA_PMK_REAUTH_THRESHOLD:
22838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (value > 0 && value <= 100)
22848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->dot11RSNAConfigPMKReauthThreshold = value;
22858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
22868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = -1;
22878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
22888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case RSNA_SA_TIMEOUT:
22898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (value > 0)
22908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->dot11RSNAConfigSATimeout = value;
22918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
22928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = -1;
22938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
22948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_PARAM_PROTO:
22958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->proto = value;
22968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
22978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_PARAM_PAIRWISE:
22988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->pairwise_cipher = value;
22998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
23008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_PARAM_GROUP:
23018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->group_cipher = value;
23028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
23038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_PARAM_KEY_MGMT:
23048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->key_mgmt = value;
23058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
23068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W
23078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_PARAM_MGMT_GROUP:
23088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->mgmt_group_cipher = value;
23098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
23108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */
23118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_PARAM_RSN_ENABLED:
23128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->rsn_enabled = value;
23138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
23148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_PARAM_MFP:
23158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->mfp = value;
23168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
23178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
23188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
23198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
23228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
23268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_get_param - Get WPA state machine parameters
23278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
23288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @param: Parameter field
23298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Parameter value
23308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
23318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtunsigned int wpa_sm_get_param(struct wpa_sm *sm, enum wpa_sm_conf_params param)
23328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
23348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
23358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (param) {
23378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case RSNA_PMK_LIFETIME:
23388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return sm->dot11RSNAConfigPMKLifetime;
23398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case RSNA_PMK_REAUTH_THRESHOLD:
23408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return sm->dot11RSNAConfigPMKReauthThreshold;
23418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case RSNA_SA_TIMEOUT:
23428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return sm->dot11RSNAConfigSATimeout;
23438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_PARAM_PROTO:
23448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return sm->proto;
23458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_PARAM_PAIRWISE:
23468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return sm->pairwise_cipher;
23478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_PARAM_GROUP:
23488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return sm->group_cipher;
23498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_PARAM_KEY_MGMT:
23508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return sm->key_mgmt;
23518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W
23528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_PARAM_MGMT_GROUP:
23538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return sm->mgmt_group_cipher;
23548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */
23558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_PARAM_RSN_ENABLED:
23568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return sm->rsn_enabled;
23578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
23588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
23598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
23648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_get_status - Get WPA state machine
23658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
23668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Buffer for status information
23678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buflen: Maximum buffer length
23688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @verbose: Whether to include verbose status information
23698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Number of bytes written to buf.
23708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
23718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Query WPA state machine for status information. This function fills in
23728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * a text area with current status information. If the buffer (buf) is not
23738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * large enough, status information will be truncated to fit the buffer.
23748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
23758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_get_status(struct wpa_sm *sm, char *buf, size_t buflen,
23768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      int verbose)
23778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *pos = buf, *end = buf + buflen;
23798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
23808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = os_snprintf(pos, end - pos,
23828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "pairwise_cipher=%s\n"
23838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "group_cipher=%s\n"
23848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "key_mgmt=%s\n",
23858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  wpa_cipher_txt(sm->pairwise_cipher),
23868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  wpa_cipher_txt(sm->group_cipher),
23878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  wpa_key_mgmt_txt(sm->key_mgmt, sm->proto));
23888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret < 0 || ret >= end - pos)
23898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return pos - buf;
23908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += ret;
2391d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
2392d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (sm->mfp != NO_MGMT_FRAME_PROTECTION && sm->ap_rsn_ie) {
2393d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		struct wpa_ie_data rsn;
2394d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		if (wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, &rsn)
2395d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		    >= 0 &&
2396d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		    rsn.capabilities & (WPA_CAPABILITY_MFPR |
2397d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt					WPA_CAPABILITY_MFPC)) {
2398d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			ret = os_snprintf(pos, end - pos, "pmf=%d\n",
2399d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt					  (rsn.capabilities &
2400d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt					   WPA_CAPABILITY_MFPR) ? 2 : 1);
2401d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			if (ret < 0 || ret >= end - pos)
2402d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				return pos - buf;
2403d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			pos += ret;
2404d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		}
2405d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	}
2406d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
24078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return pos - buf;
24088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2411f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidtint wpa_sm_pmf_enabled(struct wpa_sm *sm)
2412f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt{
2413f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt	struct wpa_ie_data rsn;
2414f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt
2415f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt	if (sm->mfp == NO_MGMT_FRAME_PROTECTION || !sm->ap_rsn_ie)
2416f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt		return 0;
2417f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt
2418f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt	if (wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, &rsn) >= 0 &&
2419f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt	    rsn.capabilities & (WPA_CAPABILITY_MFPR | WPA_CAPABILITY_MFPC))
2420f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt		return 1;
2421f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt
2422f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt	return 0;
2423f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt}
2424f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt
2425f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt
24268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
24278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_assoc_wpa_ie_default - Generate own WPA/RSN IE from configuration
24288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
24298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_ie: Pointer to buffer for WPA/RSN IE
24308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_ie_len: Pointer to the length of the wpa_ie buffer
24318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
24328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
24338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_set_assoc_wpa_ie_default(struct wpa_sm *sm, u8 *wpa_ie,
24348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    size_t *wpa_ie_len)
24358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
24378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
24398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
24408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = wpa_gen_wpa_ie(sm, wpa_ie, *wpa_ie_len);
24428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0)
24438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
24448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*wpa_ie_len = res;
24458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "WPA: Set own WPA IE default",
24478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    wpa_ie, *wpa_ie_len);
24488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->assoc_wpa_ie == NULL) {
24508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
24518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Make a copy of the WPA/RSN IE so that 4-Way Handshake gets
24528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * the correct version of the IE even if PMKSA caching is
24538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * aborted (which would remove PMKID from IE generation).
24548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
24558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->assoc_wpa_ie = os_malloc(*wpa_ie_len);
24568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->assoc_wpa_ie == NULL)
24578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
24588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(sm->assoc_wpa_ie, wpa_ie, *wpa_ie_len);
24608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->assoc_wpa_ie_len = *wpa_ie_len;
24618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
24648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
24688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_assoc_wpa_ie - Set own WPA/RSN IE from (Re)AssocReq
24698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
24708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ie: Pointer to IE data (starting from id)
24718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: IE length
24728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
24738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
24748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Inform WPA state machine about the WPA/RSN IE used in (Re)Association
24758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Request frame. The IE will be used to override the default value generated
24768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * with wpa_sm_set_assoc_wpa_ie_default().
24778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
24788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_set_assoc_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len)
24798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
24818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
24828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sm->assoc_wpa_ie);
24848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie == NULL || len == 0) {
24858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
24868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: clearing own WPA/RSN IE");
24878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->assoc_wpa_ie = NULL;
24888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->assoc_wpa_ie_len = 0;
24898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
24908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "WPA: set own WPA/RSN IE", ie, len);
24918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->assoc_wpa_ie = os_malloc(len);
24928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->assoc_wpa_ie == NULL)
24938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
24948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(sm->assoc_wpa_ie, ie, len);
24968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->assoc_wpa_ie_len = len;
24978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
25008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
25048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_ap_wpa_ie - Set AP WPA IE from Beacon/ProbeResp
25058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
25068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ie: Pointer to IE data (starting from id)
25078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: IE length
25088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
25098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
25108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Inform WPA state machine about the WPA IE used in Beacon / Probe Response
25118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * frame.
25128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
25138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_set_ap_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len)
25148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
25168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
25178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sm->ap_wpa_ie);
25198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie == NULL || len == 0) {
25208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
25218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: clearing AP WPA IE");
25228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->ap_wpa_ie = NULL;
25238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->ap_wpa_ie_len = 0;
25248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
25258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "WPA: set AP WPA IE", ie, len);
25268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->ap_wpa_ie = os_malloc(len);
25278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->ap_wpa_ie == NULL)
25288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
25298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(sm->ap_wpa_ie, ie, len);
25318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->ap_wpa_ie_len = len;
25328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
25358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
25398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_ap_rsn_ie - Set AP RSN IE from Beacon/ProbeResp
25408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
25418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ie: Pointer to IE data (starting from id)
25428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: IE length
25438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
25448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
25458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Inform WPA state machine about the RSN IE used in Beacon / Probe Response
25468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * frame.
25478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
25488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, size_t len)
25498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
25518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
25528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sm->ap_rsn_ie);
25548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie == NULL || len == 0) {
25558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
25568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: clearing AP RSN IE");
25578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->ap_rsn_ie = NULL;
25588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->ap_rsn_ie_len = 0;
25598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
25608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "WPA: set AP RSN IE", ie, len);
25618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->ap_rsn_ie = os_malloc(len);
25628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->ap_rsn_ie == NULL)
25638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
25648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(sm->ap_rsn_ie, ie, len);
25668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->ap_rsn_ie_len = len;
25678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
25708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
25748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_parse_own_wpa_ie - Parse own WPA/RSN IE
25758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
25768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Pointer to data area for parsing results
25778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 if IE is not known, or -2 on parsing failure
25788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
25798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Parse the contents of the own WPA or RSN IE from (Re)AssocReq and write the
25808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * parsed data into data.
25818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
25828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_parse_own_wpa_ie(struct wpa_sm *sm, struct wpa_ie_data *data)
25838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
25858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
25868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->assoc_wpa_ie == NULL) {
25888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
25898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: No WPA/RSN IE available from association info");
25908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
25918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_parse_wpa_ie(sm->assoc_wpa_ie, sm->assoc_wpa_ie_len, data))
25938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -2;
25948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
25958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_pmksa_cache_list(struct wpa_sm *sm, char *buf, size_t len)
25998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return pmksa_cache_list(sm->pmksa, buf, len);
26018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_drop_sa(struct wpa_sm *sm)
26058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Clear old PMK and PTK");
26078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->ptk_set = 0;
26088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->tptk_set = 0;
26098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(sm->pmk, 0, sizeof(sm->pmk));
26108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&sm->ptk, 0, sizeof(sm->ptk));
26118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&sm->tptk, 0, sizeof(sm->tptk));
26128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_has_ptk(struct wpa_sm *sm)
26168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
26188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
26198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return sm->ptk_set;
26208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
26221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
26231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtvoid wpa_sm_update_replay_ctr(struct wpa_sm *sm, const u8 *replay_ctr)
26241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
26251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	os_memcpy(sm->rx_replay_counter, replay_ctr, WPA_REPLAY_COUNTER_LEN);
26261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
26271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
26281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
26291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtvoid wpa_sm_pmksa_cache_flush(struct wpa_sm *sm, void *network_ctx)
26301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
2631f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt	pmksa_cache_flush(sm->pmksa, network_ctx, NULL, 0);
26321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
263361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
263461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
2635a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt#ifdef CONFIG_WNM
263661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 subelem_id, u8 *buf)
263761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
263861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	struct wpa_gtk_data gd;
263961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_IEEE80211W
264061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	struct wpa_igtk_kde igd;
264161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	u16 keyidx;
264261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_IEEE80211W */
264361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	u16 keyinfo;
264461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	u8 keylen;  /* plaintext key len */
264561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	u8 *key_rsc;
264661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
264761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	os_memset(&gd, 0, sizeof(gd));
264861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_IEEE80211W
264961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	os_memset(&igd, 0, sizeof(igd));
265061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_IEEE80211W */
265161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
26524530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	keylen = wpa_cipher_key_len(sm->group_cipher);
26534530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	gd.key_rsc_len = wpa_cipher_rsc_len(sm->group_cipher);
26544530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	gd.alg = wpa_cipher_to_alg(sm->group_cipher);
26554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (gd.alg == WPA_ALG_NONE) {
265661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpa_printf(MSG_DEBUG, "Unsupported group cipher suite");
265761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return -1;
265861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
265961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
266061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (subelem_id == WNM_SLEEP_SUBELEM_GTK) {
266161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		key_rsc = buf + 5;
2662a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		keyinfo = WPA_GET_LE16(buf + 2);
266361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		gd.gtk_len = keylen;
266461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (gd.gtk_len != buf[4]) {
266561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpa_printf(MSG_DEBUG, "GTK len mismatch len %d vs %d",
266661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				   gd.gtk_len, buf[4]);
266761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
266861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
266961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		gd.keyidx = keyinfo & 0x03; /* B0 - B1 */
267061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		gd.tx = wpa_supplicant_gtk_tx_bit_workaround(
267161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		         sm, !!(keyinfo & WPA_KEY_INFO_TXRX));
267261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
2673a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		os_memcpy(gd.gtk, buf + 13, gd.gtk_len);
267461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
267561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpa_hexdump_key(MSG_DEBUG, "Install GTK (WNM SLEEP)",
267661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				gd.gtk, gd.gtk_len);
267761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (wpa_supplicant_install_gtk(sm, &gd, key_rsc)) {
267861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpa_printf(MSG_DEBUG, "Failed to install the GTK in "
267961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				   "WNM mode");
268061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
268161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
268261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_IEEE80211W
268361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else if (subelem_id == WNM_SLEEP_SUBELEM_IGTK) {
268461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		os_memcpy(igd.keyid, buf + 2, 2);
268561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		os_memcpy(igd.pn, buf + 4, 6);
268661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
268761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		keyidx = WPA_GET_LE16(igd.keyid);
2688a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		os_memcpy(igd.igtk, buf + 10, WPA_IGTK_LEN);
268961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
269061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpa_hexdump_key(MSG_DEBUG, "Install IGTK (WNM SLEEP)",
269161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				igd.igtk, WPA_IGTK_LEN);
269261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (wpa_sm_set_key(sm, WPA_ALG_IGTK, broadcast_ether_addr,
269361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				   keyidx, 0, igd.pn, sizeof(igd.pn),
269461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				   igd.igtk, WPA_IGTK_LEN) < 0) {
269561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpa_printf(MSG_DEBUG, "Failed to install the IGTK in "
269661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				   "WNM mode");
269761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
269861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
269961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_IEEE80211W */
270061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else {
270161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpa_printf(MSG_DEBUG, "Unknown element id");
270261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return -1;
270361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
270461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
270561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
270661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
2707a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt#endif /* CONFIG_WNM */
2708