18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPA Supplicant - WPA state machine and EAPOL-Key processing
3807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt * Copyright (c) 2003-2015, 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)
30807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt * @kck_len: KCK length in octets
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ver: Version field from Key Info
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @dest: Destination address for the frame
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @proto: Ethertype (usually ETH_P_EAPOL)
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @msg: EAPOL-Key message
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @msg_len: Length of message
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @key_mic: Pointer to the buffer to which the EAPOL-Key MIC is written
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
38807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidtvoid wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck, size_t kck_len,
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			int ver, const u8 *dest, u16 proto,
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u8 *msg, size_t msg_len, u8 *key_mic)
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
42807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	size_t mic_len = wpa_mic_len(sm->key_mgmt);
43807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (is_zero_ether_addr(dest) && is_zero_ether_addr(sm->bssid)) {
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Association event was not yet received; try to fetch
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * BSSID from the driver.
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_sm_get_bssid(sm, sm->bssid) < 0) {
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Failed to read BSSID for "
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"EAPOL-Key destination address");
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dest = sm->bssid;
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Use BSSID (" MACSTR
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				") as the destination for EAPOL-Key",
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MAC2STR(dest));
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (key_mic &&
62807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	    wpa_eapol_key_mic(kck, kck_len, sm->key_mgmt, ver, msg, msg_len,
63807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt			      key_mic)) {
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			"WPA: Failed to generate EAPOL-Key version %d key_mgmt 0x%x MIC",
666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			ver, sm->key_mgmt);
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
69807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	wpa_hexdump_key(MSG_DEBUG, "WPA: KCK", kck, kck_len);
70807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "WPA: Derived Key MIC", key_mic, mic_len);
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "WPA: TX EAPOL-Key", msg, msg_len);
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_sm_ether_send(sm, dest, proto, msg, msg_len);
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_sm_notify_tx_eapol_key(sm->eapol);
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtout:
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(msg);
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_key_request - Send EAPOL-Key Request
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @error: Indicate whether this is an Michael MIC error report
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pairwise: 1 = error report for pairwise packet, 0 = for group packet
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Send an EAPOL-Key Request to the current authenticator. This function is
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * used to request rekeying and it is usually called when a local Michael MIC
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * failure is detected.
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise)
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
91807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	size_t mic_len, hdrlen, rlen;
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_eapol_key *reply;
93807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	struct wpa_eapol_key_192 *reply192;
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int key_info, ver;
95807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	u8 bssid[ETH_ALEN], *rbuf, *key_mic;
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (sm->key_mgmt == WPA_KEY_MGMT_OSEN ||
986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	    wpa_key_mgmt_suite_b(sm->key_mgmt))
99f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		ver = WPA_KEY_INFO_TYPE_AKM_DEFINED;
100f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	else if (wpa_key_mgmt_ft(sm->key_mgmt) ||
101f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		 wpa_key_mgmt_sha256(sm->key_mgmt))
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ver = WPA_KEY_INFO_TYPE_AES_128_CMAC;
10361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	else if (sm->pairwise_cipher != WPA_CIPHER_TKIP)
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_sm_get_bssid(sm, bssid) < 0) {
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Failed to read BSSID for EAPOL-Key request");
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
114807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	mic_len = wpa_mic_len(sm->key_mgmt);
115807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	hdrlen = mic_len == 24 ? sizeof(*reply192) : sizeof(*reply);
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
117807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt				  hdrlen, &rlen, (void *) &reply);
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (rbuf == NULL)
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
120807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	reply192 = (struct wpa_eapol_key_192 *) reply;
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
122f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	reply->type = (sm->proto == WPA_PROTO_RSN ||
123f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		       sm->proto == WPA_PROTO_OSEN) ?
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key_info = WPA_KEY_INFO_REQUEST | ver;
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->ptk_set)
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_info |= WPA_KEY_INFO_MIC;
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (error)
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_info |= WPA_KEY_INFO_ERROR;
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pairwise)
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_info |= WPA_KEY_INFO_KEY_TYPE;
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE16(reply->key_info, key_info);
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE16(reply->key_length, 0);
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(reply->replay_counter, sm->request_counter,
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  WPA_REPLAY_COUNTER_LEN);
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN);
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
138807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	if (mic_len == 24)
139807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt		WPA_PUT_BE16(reply192->key_data_length, 0);
140807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	else
141807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt		WPA_PUT_BE16(reply->key_data_length, 0);
142807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	if (!(key_info & WPA_KEY_INFO_MIC))
143807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt		key_mic = NULL;
144807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	else
145807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt		key_mic = reply192->key_mic; /* same offset in reply */
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"WPA: Sending EAPOL-Key Request (error=%d "
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"pairwise=%d ptk_set=%d len=%lu)",
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		error, pairwise, sm->ptk_set, (unsigned long) rlen);
151807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver, bssid,
152807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt			   ETH_P_EAPOL, rbuf, rlen, key_mic);
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic void wpa_supplicant_key_mgmt_set_pmk(struct wpa_sm *sm)
1576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
1586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#ifdef CONFIG_IEEE80211R
1596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (sm->key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X) {
1606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (wpa_sm_key_mgmt_set_pmk(sm, sm->xxkey, sm->xxkey_len))
1616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
1626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				"RSN: Cannot set low order 256 bits of MSK for key management offload");
1636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	} else {
1646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif /* CONFIG_IEEE80211R */
1656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (wpa_sm_key_mgmt_set_pmk(sm, sm->pmk, sm->pmk_len))
1666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
1676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				"RSN: Cannot set PMK for key management offload");
1686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#ifdef CONFIG_IEEE80211R
1696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
1706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif /* CONFIG_IEEE80211R */
1716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
1726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_get_pmk(struct wpa_sm *sm,
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  const unsigned char *src_addr,
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  const u8 *pmkid)
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int abort_cached = 0;
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pmkid && !sm->cur_pmksa) {
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* When using drivers that generate RSN IE, wpa_supplicant may
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * not have enough time to get the association information
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * event before receiving this 1/4 message, so try to find a
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * matching PMKSA cache entry here. */
185c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		sm->cur_pmksa = pmksa_cache_get(sm->pmksa, src_addr, pmkid,
186c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt						NULL);
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->cur_pmksa) {
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"RSN: found matching PMKID from PMKSA cache");
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"RSN: no matching PMKID found");
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			abort_cached = 1;
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pmkid && sm->cur_pmksa &&
198c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt	    os_memcmp_const(pmkid, sm->cur_pmksa->pmkid, PMKID_LEN) == 0) {
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "RSN: matched PMKID", pmkid, PMKID_LEN);
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_sm_set_pmk_from_pmksa(sm);
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump_key(MSG_DEBUG, "RSN: PMK from PMKSA cache",
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				sm->pmk, sm->pmk_len);
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eapol_sm_notify_cached(sm->eapol);
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->xxkey_len = 0;
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt) && sm->eapol) {
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int res, pmk_len;
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pmk_len = PMK_LEN;
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = eapol_sm_get_key(sm->eapol, sm->pmk, PMK_LEN);
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res) {
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/*
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * EAP-LEAP is an exception from other EAP methods: it
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * uses only 16-byte PMK.
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 */
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			res = eapol_sm_get_key(sm->eapol, sm->pmk, 16);
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pmk_len = 16;
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u8 buf[2 * PMK_LEN];
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (eapol_sm_get_key(sm->eapol, buf, 2 * PMK_LEN) == 0)
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			{
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				os_memcpy(sm->xxkey, buf + PMK_LEN, PMK_LEN);
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				sm->xxkey_len = PMK_LEN;
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				os_memset(buf, 0, sizeof(buf));
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res == 0) {
23061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			struct rsn_pmksa_cache_entry *sa = NULL;
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump_key(MSG_DEBUG, "WPA: PMK from EAPOL state "
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"machines", sm->pmk, pmk_len);
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->pmk_len = pmk_len;
2346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			wpa_supplicant_key_mgmt_set_pmk(sm);
235c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt			if (sm->proto == WPA_PROTO_RSN &&
2366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			    !wpa_key_mgmt_suite_b(sm->key_mgmt) &&
237c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt			    !wpa_key_mgmt_ft(sm->key_mgmt)) {
23861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				sa = pmksa_cache_add(sm->pmksa,
23961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt						     sm->pmk, pmk_len,
2406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt						     NULL, 0,
24161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt						     src_addr, sm->own_addr,
24261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt						     sm->network_ctx,
24361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt						     sm->key_mgmt);
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (!sm->cur_pmksa && pmkid &&
246c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			    pmksa_cache_get(sm->pmksa, src_addr, pmkid, NULL))
247c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			{
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"RSN: the new PMK matches with the "
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"PMKID");
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				abort_cached = 0;
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
25361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
25461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			if (!sm->cur_pmksa)
25561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				sm->cur_pmksa = sa;
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Failed to get master session key from "
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"EAPOL state machines - key handshake "
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"aborted");
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (sm->cur_pmksa) {
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"RSN: Cancelled PMKSA caching "
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"attempt");
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				sm->cur_pmksa = NULL;
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				abort_cached = 1;
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			} else if (!abort_cached) {
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return -1;
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
273c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	if (abort_cached && wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt) &&
2746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	    !wpa_key_mgmt_suite_b(sm->key_mgmt) &&
275f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	    !wpa_key_mgmt_ft(sm->key_mgmt) && sm->key_mgmt != WPA_KEY_MGMT_OSEN)
276f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	{
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Send EAPOL-Start to trigger full EAP authentication. */
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		u8 *buf;
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		size_t buflen;
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"RSN: no PMKSA entry found - trigger "
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"full EAP authentication");
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		buf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_START,
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 NULL, 0, &buflen, NULL);
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (buf) {
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_sm_ether_send(sm, sm->bssid, ETH_P_EAPOL,
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  buf, buflen);
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(buf);
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -2;
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_supplicant_send_2_of_4 - Send message 2 of WPA/RSN 4-Way Handshake
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @dst: Destination address for the frame
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @key: Pointer to the EAPOL-Key frame header
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ver: Version bits from EAPOL-Key Key Info
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @nonce: Nonce value for the EAPOL-Key frame
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_ie: WPA/RSN IE
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_ie_len: Length of the WPA/RSN IE
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ptk: PTK to use for keyed hash and encryption
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       const struct wpa_eapol_key *key,
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       int ver, const u8 *nonce,
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       const u8 *wpa_ie, size_t wpa_ie_len,
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       struct wpa_ptk *ptk)
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
318807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	size_t mic_len, hdrlen, rlen;
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_eapol_key *reply;
320807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	struct wpa_eapol_key_192 *reply192;
321807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	u8 *rbuf, *key_mic;
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *rsn_ie_buf = NULL;
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_ie == NULL) {
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: No wpa_ie set - "
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"cannot generate msg 2/4");
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_key_mgmt_ft(sm->key_mgmt)) {
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int res;
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Add PMKR1Name into RSN IE (PMKID-List) and add MDIE and
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * FTIE from (Re)Association Response.
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		rsn_ie_buf = os_malloc(wpa_ie_len + 2 + 2 + PMKID_LEN +
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       sm->assoc_resp_ies_len);
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (rsn_ie_buf == NULL)
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(rsn_ie_buf, wpa_ie, wpa_ie_len);
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = wpa_insert_pmkid(rsn_ie_buf, wpa_ie_len,
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       sm->pmk_r1_name);
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res < 0) {
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(rsn_ie_buf);
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_ie_len += res;
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->assoc_resp_ies) {
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(rsn_ie_buf + wpa_ie_len, sm->assoc_resp_ies,
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  sm->assoc_resp_ies_len);
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_ie_len += sm->assoc_resp_ies_len;
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_ie = rsn_ie_buf;
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "WPA: WPA IE for msg 2/4", wpa_ie, wpa_ie_len);
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
363807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	mic_len = wpa_mic_len(sm->key_mgmt);
364807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	hdrlen = mic_len == 24 ? sizeof(*reply192) : sizeof(*reply);
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY,
366807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt				  NULL, hdrlen + wpa_ie_len,
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  &rlen, (void *) &reply);
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (rbuf == NULL) {
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(rsn_ie_buf);
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
372807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	reply192 = (struct wpa_eapol_key_192 *) reply;
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
374f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	reply->type = (sm->proto == WPA_PROTO_RSN ||
375f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		       sm->proto == WPA_PROTO_OSEN) ?
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE16(reply->key_info,
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_MIC);
379f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN)
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		WPA_PUT_BE16(reply->key_length, 0);
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(reply->key_length, key->key_length, 2);
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(reply->replay_counter, key->replay_counter,
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  WPA_REPLAY_COUNTER_LEN);
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "WPA: Replay Counter", reply->replay_counter,
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    WPA_REPLAY_COUNTER_LEN);
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
388807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	key_mic = reply192->key_mic; /* same offset for reply and reply192 */
389807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	if (mic_len == 24) {
390807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt		WPA_PUT_BE16(reply192->key_data_length, wpa_ie_len);
391807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt		os_memcpy(reply192 + 1, wpa_ie, wpa_ie_len);
392807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	} else {
393807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt		WPA_PUT_BE16(reply->key_data_length, wpa_ie_len);
394807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt		os_memcpy(reply + 1, wpa_ie, wpa_ie_len);
395807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	}
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(rsn_ie_buf);
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(reply->key_nonce, nonce, WPA_NONCE_LEN);
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 2/4");
401807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	wpa_eapol_key_send(sm, ptk->kck, ptk->kck_len, ver, dst, ETH_P_EAPOL,
402807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt			   rbuf, rlen, key_mic);
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr,
409807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt			  const struct wpa_eapol_key *key, struct wpa_ptk *ptk)
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_key_mgmt_ft(sm->key_mgmt))
413807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt		return wpa_derive_ptk_ft(sm, src_addr, key, ptk);
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
416807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	return wpa_pmk_to_ptk(sm->pmk, sm->pmk_len, "Pairwise key expansion",
417807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt			      sm->own_addr, sm->bssid, sm->snonce,
418807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt			      key->key_nonce, ptk, sm->key_mgmt,
419807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt			      sm->pairwise_cipher);
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_process_1_of_4(struct wpa_sm *sm,
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  const unsigned char *src_addr,
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  const struct wpa_eapol_key *key,
42643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt					  u16 ver, const u8 *key_data,
42743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt					  size_t key_data_len)
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_eapol_ie_parse ie;
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ptk *ptk;
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
432cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	u8 *kde, *kde_buf = NULL;
433cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	size_t kde_len;
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_sm_get_network_ctx(sm) == NULL) {
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: No SSID info "
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"found (msg 1 of 4)");
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE);
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: RX message 1 of 4-Way "
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"Handshake from " MACSTR " (ver=%d)", MAC2STR(src_addr), ver);
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&ie, 0, sizeof(ie));
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
447f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) {
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* RSN: msg 1/4 should contain PMKID for the selected PMK */
44943cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		wpa_hexdump(MSG_DEBUG, "RSN: msg 1/4 key data",
45043cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt			    key_data, key_data_len);
45143cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0)
4521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			goto failed;
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ie.pmkid) {
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump(MSG_DEBUG, "RSN: PMKID from "
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    "Authenticator", ie.pmkid, PMKID_LEN);
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = wpa_supplicant_get_pmk(sm, src_addr, ie.pmkid);
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res == -2) {
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: Do not reply to "
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"msg 1/4 - requesting full EAP authentication");
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res)
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->renew_snonce) {
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (random_get_bytes(sm->snonce, WPA_NONCE_LEN)) {
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Failed to get random data for SNonce");
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto failed;
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->renew_snonce = 0;
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "WPA: Renewed SNonce",
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    sm->snonce, WPA_NONCE_LEN);
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Calculate PTK which will be stored as a temporary PTK until it has
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * been verified when processing message 3/4. */
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ptk = &sm->tptk;
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_derive_ptk(sm, src_addr, key, ptk);
4839866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt	if (sm->pairwise_cipher == WPA_CIPHER_TKIP) {
48461593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		u8 buf[8];
4859866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt		/* Supplicant: swap tx/rx Mic keys */
486807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt		os_memcpy(buf, &ptk->tk[16], 8);
487807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt		os_memcpy(&ptk->tk[16], &ptk->tk[24], 8);
488807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt		os_memcpy(&ptk->tk[24], buf, 8);
48961593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		os_memset(buf, 0, sizeof(buf));
4909866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt	}
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->tptk_set = 1;
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
493cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	kde = sm->assoc_wpa_ie;
494cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	kde_len = sm->assoc_wpa_ie_len;
495cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
496cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#ifdef CONFIG_P2P
497cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (sm->p2p) {
498cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		kde_buf = os_malloc(kde_len + 2 + RSN_SELECTOR_LEN + 1);
499cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		if (kde_buf) {
500cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			u8 *pos;
501cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			wpa_printf(MSG_DEBUG, "P2P: Add IP Address Request KDE "
502cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt				   "into EAPOL-Key 2/4");
503cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			os_memcpy(kde_buf, kde, kde_len);
504cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			kde = kde_buf;
505cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			pos = kde + kde_len;
506cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			*pos++ = WLAN_EID_VENDOR_SPECIFIC;
507cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			*pos++ = RSN_SELECTOR_LEN + 1;
508cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			RSN_SELECTOR_PUT(pos, WFA_KEY_DATA_IP_ADDR_REQ);
509cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			pos += RSN_SELECTOR_LEN;
510cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			*pos++ = 0x01;
511cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			kde_len = pos - kde;
512cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		}
513cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	}
514cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#endif /* CONFIG_P2P */
515cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_supplicant_send_2_of_4(sm, sm->bssid, key, ver, sm->snonce,
517cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt				       kde, kde_len, ptk))
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
520cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	os_free(kde_buf);
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(sm->anonce, key->key_nonce, WPA_NONCE_LEN);
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return;
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfailed:
525cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	os_free(kde_buf);
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_sm_start_preauth(void *eloop_ctx, void *timeout_ctx)
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_sm *sm = eloop_ctx;
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rsn_preauth_candidate_process(sm);
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_key_neg_complete(struct wpa_sm *sm,
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    const u8 *addr, int secure)
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"WPA: Key negotiation completed with "
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MACSTR " [PTK=%s GTK=%s]", MAC2STR(addr),
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_cipher_txt(sm->pairwise_cipher),
5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_cipher_txt(sm->group_cipher));
5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_sm_cancel_auth_timeout(sm);
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_sm_set_state(sm, WPA_COMPLETED);
5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (secure) {
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_sm_mlme_setprotection(
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm, addr, MLME_SETPROTECTION_PROTECT_TYPE_RX_TX,
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eapol_sm_notify_portValid(sm->eapol, TRUE);
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_key_mgmt_wpa_psk(sm->key_mgmt))
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eapol_sm_notify_eap_success(sm->eapol, TRUE);
5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Start preauthentication after a short wait to avoid a
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * possible race condition between the data receive and key
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * configuration after the 4-Way Handshake. This increases the
5591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * likelihood of the first preauth EAPOL-Start frame getting to
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * the target AP.
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(1, 0, wpa_sm_start_preauth, sm, NULL);
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->cur_pmksa && sm->cur_pmksa->opportunistic) {
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"RSN: Authenticator accepted "
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"opportunistic PMKSA entry - marking it valid");
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->cur_pmksa->opportunistic = 0;
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_key_mgmt_ft(sm->key_mgmt)) {
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Prepare for the next transition */
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_ft_prepare_auth_request(sm, NULL);
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_sm_rekey_ptk(void *eloop_ctx, void *timeout_ctx)
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_sm *sm = eloop_ctx;
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Request PTK rekeying");
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_sm_key_request(sm, 0, 1);
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_install_ptk(struct wpa_sm *sm,
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const struct wpa_eapol_key *key)
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int keylen, rsclen;
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum wpa_alg alg;
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *key_rsc;
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 null_rsc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"WPA: Installing PTK to the driver");
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6004530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (sm->pairwise_cipher == WPA_CIPHER_NONE) {
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Pairwise Cipher "
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Suite: NONE - do not use pairwise keys");
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
6044530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	}
6054530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
6064530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (!wpa_cipher_valid_pairwise(sm->pairwise_cipher)) {
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: Unsupported pairwise cipher %d",
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->pairwise_cipher);
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6134530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	alg = wpa_cipher_to_alg(sm->pairwise_cipher);
6144530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	keylen = wpa_cipher_key_len(sm->pairwise_cipher);
6154530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	rsclen = wpa_cipher_rsc_len(sm->pairwise_cipher);
6164530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt
617f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) {
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_rsc = null_rsc;
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_rsc = key->key_rsc;
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "WPA: RSC", key_rsc, rsclen);
6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_sm_set_key(sm, alg, sm->bssid, 0, 1, key_rsc, rsclen,
625807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt			   sm->ptk.tk, keylen) < 0) {
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: Failed to set PTK to the "
6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"driver (alg=%d keylen=%d bssid=" MACSTR ")",
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			alg, keylen, MAC2STR(sm->bssid));
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	/* TK is not needed anymore in supplicant */
634807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	os_memset(sm->ptk.tk, 0, WPA_TK_MAX_LEN);
6356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->wpa_ptk_rekey) {
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL);
6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(sm->wpa_ptk_rekey, 0, wpa_sm_rekey_ptk,
6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       sm, NULL);
6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_check_group_cipher(struct wpa_sm *sm,
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     int group_cipher,
6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     int keylen, int maxkeylen,
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     int *key_rsc_len,
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     enum wpa_alg *alg)
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6524530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	int klen;
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6544530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	*alg = wpa_cipher_to_alg(group_cipher);
6554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (*alg == WPA_ALG_NONE) {
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: Unsupported Group Cipher %d",
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			group_cipher);
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6614530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	*key_rsc_len = wpa_cipher_rsc_len(group_cipher);
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	klen = wpa_cipher_key_len(group_cipher);
6644530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (keylen != klen || maxkeylen < klen) {
6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: Unsupported %s Group Cipher key length %d (%d)",
6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_cipher_txt(group_cipher), keylen, maxkeylen);
6684530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		return -1;
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6704530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	return 0;
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_gtk_data {
6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum wpa_alg alg;
6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int tx, key_rsc_len, keyidx;
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 gtk[32];
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int gtk_len;
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_install_gtk(struct wpa_sm *sm,
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const struct wpa_gtk_data *gd,
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const u8 *key_rsc)
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *_gtk = gd->gtk;
6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 gtk_buf[32];
6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_key(MSG_DEBUG, "WPA: Group Key", gd->gtk, gd->gtk_len);
6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"WPA: Installing GTK to the driver (keyidx=%d tx=%d len=%d)",
6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		gd->keyidx, gd->tx, gd->gtk_len);
6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "WPA: RSC", key_rsc, gd->key_rsc_len);
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->group_cipher == WPA_CIPHER_TKIP) {
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Swap Tx/Rx keys for Michael MIC */
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(gtk_buf, gd->gtk, 16);
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(gtk_buf + 16, gd->gtk + 24, 8);
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(gtk_buf + 24, gd->gtk + 16, 8);
6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		_gtk = gtk_buf;
7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->pairwise_cipher == WPA_CIPHER_NONE) {
7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_sm_set_key(sm, gd->alg, NULL,
7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   gd->keyidx, 1, key_rsc, gd->key_rsc_len,
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   _gtk, gd->gtk_len) < 0) {
7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Failed to set GTK to the driver "
7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"(Group only)");
70861593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt			os_memset(gtk_buf, 0, sizeof(gtk_buf));
7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (wpa_sm_set_key(sm, gd->alg, broadcast_ether_addr,
7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  gd->keyidx, gd->tx, key_rsc, gd->key_rsc_len,
7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  _gtk, gd->gtk_len) < 0) {
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: Failed to set GTK to "
7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"the driver (alg=%d keylen=%d keyidx=%d)",
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			gd->alg, gd->gtk_len, gd->keyidx);
71861593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		os_memset(gtk_buf, 0, sizeof(gtk_buf));
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
72161593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt	os_memset(gtk_buf, 0, sizeof(gtk_buf));
7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_gtk_tx_bit_workaround(const struct wpa_sm *sm,
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						int tx)
7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tx && sm->pairwise_cipher != WPA_CIPHER_NONE) {
7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Ignore Tx bit for GTK if a pairwise key is used. One AP
7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * seemed to set this bit (incorrectly, since Tx is only when
7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * doing Group Key only APs) and without this workaround, the
7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * data connection does not work because wpa_supplicant
7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * configured non-zero keyidx to be used for unicast. */
7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: Tx bit set for GTK, but pairwise "
7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"keys are used - ignore Tx bit");
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return tx;
7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_pairwise_gtk(struct wpa_sm *sm,
7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       const struct wpa_eapol_key *key,
7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       const u8 *gtk, size_t gtk_len,
7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       int key_info)
7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_gtk_data gd;
7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * IEEE Std 802.11i-2004 - 8.5.2 EAPOL-Key frames - Figure 43x
7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * GTK KDE format:
7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * KeyID[bits 0-1], Tx [bit 2], Reserved [bits 3-7]
7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Reserved [bits 0-7]
7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * GTK
7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&gd, 0, sizeof(gd));
7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_key(MSG_DEBUG, "RSN: received GTK in pairwise handshake",
7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			gtk, gtk_len);
7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (gtk_len < 2 || gtk_len - 2 > sizeof(gd.gtk))
7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gd.keyidx = gtk[0] & 0x3;
7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gd.tx = wpa_supplicant_gtk_tx_bit_workaround(sm,
7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						     !!(gtk[0] & BIT(2)));
7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gtk += 2;
7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gtk_len -= 2;
7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(gd.gtk, gtk, gtk_len);
7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gd.gtk_len = gtk_len;
7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
776fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	if (sm->group_cipher != WPA_CIPHER_GTK_NOT_USED &&
777fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	    (wpa_supplicant_check_group_cipher(sm, sm->group_cipher,
778fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt					       gtk_len, gtk_len,
779fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt					       &gd.key_rsc_len, &gd.alg) ||
780fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	     wpa_supplicant_install_gtk(sm, &gd, key->key_rsc))) {
7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"RSN: Failed to install GTK");
78361593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		os_memset(&gd, 0, sizeof(gd));
7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
78661593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt	os_memset(&gd, 0, sizeof(gd));
7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_key_neg_complete(sm, sm->bssid,
7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					key_info & WPA_KEY_INFO_SECURE);
7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ieee80211w_set_keys(struct wpa_sm *sm,
7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       struct wpa_eapol_ie_parse *ie)
7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W
798b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	if (!wpa_cipher_valid_mgmt_group(sm->mgmt_group_cipher))
7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie->igtk) {
802b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt		size_t len;
8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		const struct wpa_igtk_kde *igtk;
8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		u16 keyidx;
805b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt		len = wpa_cipher_key_len(sm->mgmt_group_cipher);
806b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt		if (ie->igtk_len != WPA_IGTK_KDE_PREFIX_LEN + len)
8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		igtk = (const struct wpa_igtk_kde *) ie->igtk;
8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		keyidx = WPA_GET_LE16(igtk->keyid);
8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: IGTK keyid %d "
8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"pn %02x%02x%02x%02x%02x%02x",
8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			keyidx, MAC2STR(igtk->pn));
8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump_key(MSG_DEBUG, "WPA: IGTK",
814b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt				igtk->igtk, len);
8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (keyidx > 4095) {
8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Invalid IGTK KeyID %d", keyidx);
8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
820b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt		if (wpa_sm_set_key(sm, wpa_cipher_to_alg(sm->mgmt_group_cipher),
821b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt				   broadcast_ether_addr,
8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   keyidx, 0, igtk->pn, sizeof(igtk->pn),
823b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt				   igtk->igtk, len) < 0) {
8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Failed to configure IGTK to the driver");
8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_IEEE80211W */
8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */
8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_report_ie_mismatch(struct wpa_sm *sm,
8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   const char *reason, const u8 *src_addr,
8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   const u8 *wpa_ie, size_t wpa_ie_len,
8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   const u8 *rsn_ie, size_t rsn_ie_len)
8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: %s (src=" MACSTR ")",
8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		reason, MAC2STR(src_addr));
8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->ap_wpa_ie) {
8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_INFO, "WPA: WPA IE in Beacon/ProbeResp",
8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    sm->ap_wpa_ie, sm->ap_wpa_ie_len);
8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_ie) {
8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!sm->ap_wpa_ie) {
8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: No WPA IE in Beacon/ProbeResp");
8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_INFO, "WPA: WPA IE in 3/4 msg",
8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    wpa_ie, wpa_ie_len);
8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->ap_rsn_ie) {
8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_INFO, "WPA: RSN IE in Beacon/ProbeResp",
8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    sm->ap_rsn_ie, sm->ap_rsn_ie_len);
8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (rsn_ie) {
8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!sm->ap_rsn_ie) {
8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: No RSN IE in Beacon/ProbeResp");
8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_INFO, "WPA: RSN IE in 3/4 msg",
8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    rsn_ie, rsn_ie_len);
8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
871d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	wpa_sm_deauthenticate(sm, WLAN_REASON_IE_IN_4WAY_DIFFERS);
8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ft_validate_mdie(struct wpa_sm *sm,
8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    const unsigned char *src_addr,
8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    struct wpa_eapol_ie_parse *ie,
8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    const u8 *assoc_resp_mdie)
8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct rsn_mdie *mdie;
8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	mdie = (struct rsn_mdie *) (ie->mdie + 2);
8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie->mdie == NULL || ie->mdie_len < 2 + sizeof(*mdie) ||
8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(mdie->mobility_domain, sm->mobility_domain,
8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      MOBILITY_DOMAIN_ID_LEN) != 0) {
8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: MDIE in msg 3/4 did "
8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"not match with the current mobility domain");
8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (assoc_resp_mdie &&
8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (assoc_resp_mdie[1] != ie->mdie[1] ||
8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     os_memcmp(assoc_resp_mdie, ie->mdie, 2 + ie->mdie[1]) != 0)) {
8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: MDIE mismatch");
8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "FT: MDIE in EAPOL-Key msg 3/4",
8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    ie->mdie, 2 + ie->mdie[1]);
8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "FT: MDIE in (Re)Association Response",
9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    assoc_resp_mdie, 2 + assoc_resp_mdie[1]);
9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ft_validate_ftie(struct wpa_sm *sm,
9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    const unsigned char *src_addr,
9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    struct wpa_eapol_ie_parse *ie,
9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    const u8 *assoc_resp_ftie)
9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie->ftie == NULL) {
9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"FT: No FTIE in EAPOL-Key msg 3/4");
9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (assoc_resp_ftie == NULL)
9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (assoc_resp_ftie[1] != ie->ftie[1] ||
9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(assoc_resp_ftie, ie->ftie, 2 + ie->ftie[1]) != 0) {
9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: FTIE mismatch");
9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "FT: FTIE in EAPOL-Key msg 3/4",
9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    ie->ftie, 2 + ie->ftie[1]);
9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "FT: FTIE in (Re)Association Response",
9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    assoc_resp_ftie, 2 + assoc_resp_ftie[1]);
9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ft_validate_rsnie(struct wpa_sm *sm,
9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     const unsigned char *src_addr,
9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     struct wpa_eapol_ie_parse *ie)
9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ie_data rsn;
9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!ie->rsn_ie)
9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Verify that PMKR1Name from EAPOL-Key message 3/4
9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * matches with the value we derived.
9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_parse_wpa_ie_rsn(ie->rsn_ie, ie->rsn_ie_len, &rsn) < 0 ||
9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    rsn.num_pmkid != 1 || rsn.pmkid == NULL) {
9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: No PMKR1Name in "
9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"FT 4-way handshake message 3/4");
9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
956c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt	if (os_memcmp_const(rsn.pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN) != 0)
957c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt	{
9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"FT: PMKR1Name mismatch in "
9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"FT 4-way handshake message 3/4");
9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from Authenticator",
9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    rsn.pmkid, WPA_PMK_NAME_LEN);
9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "FT: Derived PMKR1Name",
9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    sm->pmk_r1_name, WPA_PMK_NAME_LEN);
9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_validate_ie_ft(struct wpa_sm *sm,
9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 const unsigned char *src_addr,
9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 struct wpa_eapol_ie_parse *ie)
9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos, *end, *mdie = NULL, *ftie = NULL;
9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->assoc_resp_ies) {
9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = sm->assoc_resp_ies;
9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		end = pos + sm->assoc_resp_ies_len;
9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (pos + 2 < end) {
9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (pos + 2 + pos[1] > end)
9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			switch (*pos) {
9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			case WLAN_EID_MOBILITY_DOMAIN:
9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				mdie = pos;
9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			case WLAN_EID_FAST_BSS_TRANSITION:
9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				ftie = pos;
9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos += 2 + pos[1];
9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ft_validate_mdie(sm, src_addr, ie, mdie) < 0 ||
9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ft_validate_ftie(sm, src_addr, ie, ftie) < 0 ||
9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ft_validate_rsnie(sm, src_addr, ie) < 0)
9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_validate_ie(struct wpa_sm *sm,
10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const unsigned char *src_addr,
10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      struct wpa_eapol_ie_parse *ie)
10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->ap_wpa_ie == NULL && sm->ap_rsn_ie == NULL) {
10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: No WPA/RSN IE for this AP known. "
10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Trying to get from scan results");
10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_sm_get_beacon_ie(sm) < 0) {
10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Could not find AP from "
10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"the scan results");
10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG,
10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Found the current AP from "
10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"updated scan results");
10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie->wpa_ie == NULL && ie->rsn_ie == NULL &&
10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (sm->ap_wpa_ie || sm->ap_rsn_ie)) {
10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_report_ie_mismatch(sm, "IE in 3/4 msg does not match "
10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       "with IE in Beacon/ProbeResp (no IE?)",
10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       src_addr, ie->wpa_ie, ie->wpa_ie_len,
10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       ie->rsn_ie, ie->rsn_ie_len);
10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((ie->wpa_ie && sm->ap_wpa_ie &&
10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     (ie->wpa_ie_len != sm->ap_wpa_ie_len ||
10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	      os_memcmp(ie->wpa_ie, sm->ap_wpa_ie, ie->wpa_ie_len) != 0)) ||
10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (ie->rsn_ie && sm->ap_rsn_ie &&
10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     wpa_compare_rsn_ie(wpa_key_mgmt_ft(sm->key_mgmt),
10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				sm->ap_rsn_ie, sm->ap_rsn_ie_len,
10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				ie->rsn_ie, ie->rsn_ie_len))) {
10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_report_ie_mismatch(sm, "IE in 3/4 msg does not match "
10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       "with IE in Beacon/ProbeResp",
10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       src_addr, ie->wpa_ie, ie->wpa_ie_len,
10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       ie->rsn_ie, ie->rsn_ie_len);
10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->proto == WPA_PROTO_WPA &&
10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ie->rsn_ie && sm->ap_rsn_ie == NULL && sm->rsn_enabled) {
10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_report_ie_mismatch(sm, "Possible downgrade attack "
10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       "detected - RSN was enabled and RSN IE "
10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       "was in msg 3/4, but not in "
10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       "Beacon/ProbeResp",
10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       src_addr, ie->wpa_ie, ie->wpa_ie_len,
10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       ie->rsn_ie, ie->rsn_ie_len);
10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_key_mgmt_ft(sm->key_mgmt) &&
10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wpa_supplicant_validate_ie_ft(sm, src_addr, ie) < 0)
10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_supplicant_send_4_of_4 - Send message 4 of WPA/RSN 4-Way Handshake
10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @dst: Destination address for the frame
10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @key: Pointer to the EAPOL-Key frame header
10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ver: Version bits from EAPOL-Key Key Info
10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @key_info: Key Info
10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ptk: PTK to use for keyed hash and encryption
10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst,
10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       const struct wpa_eapol_key *key,
10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       u16 ver, u16 key_info,
10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       struct wpa_ptk *ptk)
10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1085807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	size_t mic_len, hdrlen, rlen;
10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_eapol_key *reply;
1087807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	struct wpa_eapol_key_192 *reply192;
1088807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	u8 *rbuf, *key_mic;
10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1090807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	mic_len = wpa_mic_len(sm->key_mgmt);
1091807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	hdrlen = mic_len == 24 ? sizeof(*reply192) : sizeof(*reply);
10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
1093807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt				  hdrlen, &rlen, (void *) &reply);
10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (rbuf == NULL)
10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1096807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	reply192 = (struct wpa_eapol_key_192 *) reply;
10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1098f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	reply->type = (sm->proto == WPA_PROTO_RSN ||
1099f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		       sm->proto == WPA_PROTO_OSEN) ?
11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key_info &= WPA_KEY_INFO_SECURE;
11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key_info |= ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_MIC;
11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE16(reply->key_info, key_info);
1104f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN)
11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		WPA_PUT_BE16(reply->key_length, 0);
11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(reply->key_length, key->key_length, 2);
11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(reply->replay_counter, key->replay_counter,
11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  WPA_REPLAY_COUNTER_LEN);
11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1111807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	key_mic = reply192->key_mic; /* same offset for reply and reply192 */
1112807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	if (mic_len == 24)
1113807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt		WPA_PUT_BE16(reply192->key_data_length, 0);
1114807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	else
1115807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt		WPA_PUT_BE16(reply->key_data_length, 0);
11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 4/4");
1118807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	wpa_eapol_key_send(sm, ptk->kck, ptk->kck_len, ver, dst, ETH_P_EAPOL,
1119807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt			   rbuf, rlen, key_mic);
11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_process_3_of_4(struct wpa_sm *sm,
11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  const struct wpa_eapol_key *key,
112743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt					  u16 ver, const u8 *key_data,
112843cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt					  size_t key_data_len)
11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
113043cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	u16 key_info, keylen;
11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_eapol_ie_parse ie;
11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE);
11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: RX message 3 of 4-Way "
11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"Handshake from " MACSTR " (ver=%d)", MAC2STR(sm->bssid), ver);
11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key_info = WPA_GET_BE16(key->key_info);
11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
113943cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	wpa_hexdump(MSG_DEBUG, "WPA: IE KeyData", key_data, key_data_len);
114043cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0)
11411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		goto failed;
11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: GTK IE in unencrypted key data");
11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W
11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie.igtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: IGTK KDE in unencrypted key data");
11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1154b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	if (ie.igtk &&
1155b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	    wpa_cipher_valid_mgmt_group(sm->mgmt_group_cipher) &&
1156b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	    ie.igtk_len != WPA_IGTK_KDE_PREFIX_LEN +
1157b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt	    (unsigned int) wpa_cipher_key_len(sm->mgmt_group_cipher)) {
11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: Invalid IGTK KDE length %lu",
11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			(unsigned long) ie.igtk_len);
11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */
11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_supplicant_validate_ie(sm, sm->bssid, &ie) < 0)
11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(sm->anonce, key->key_nonce, WPA_NONCE_LEN) != 0) {
11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: ANonce from message 1 of 4-Way Handshake "
11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"differs from 3 of 4-Way Handshake - drop packet (src="
11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MACSTR ")", MAC2STR(sm->bssid));
11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	keylen = WPA_GET_BE16(key->key_length);
11774530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	if (keylen != wpa_cipher_key_len(sm->pairwise_cipher)) {
11784530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
11794530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			"WPA: Invalid %s key length %d (src=" MACSTR
11804530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			")", wpa_cipher_txt(sm->pairwise_cipher), keylen,
11814530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			MAC2STR(sm->bssid));
11824530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		goto failed;
11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1185cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#ifdef CONFIG_P2P
1186cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (ie.ip_addr_alloc) {
1187cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		os_memcpy(sm->p2p_ip_addr, ie.ip_addr_alloc, 3 * 4);
1188cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		wpa_hexdump(MSG_DEBUG, "P2P: IP address info",
1189cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			    sm->p2p_ip_addr, sizeof(sm->p2p_ip_addr));
1190cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	}
1191cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#endif /* CONFIG_P2P */
1192cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_supplicant_send_4_of_4(sm, sm->bssid, key, ver, key_info,
119421de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt				       &sm->ptk)) {
11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* SNonce was successfully used in msg 3/4, so mark it to be renewed
11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * for the next 4-Way Handshake. If msg 3 is received again, the old
12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * SNonce will still be used to avoid changing PTK. */
12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->renew_snonce = 1;
12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (key_info & WPA_KEY_INFO_INSTALL) {
12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_supplicant_install_ptk(sm, key))
12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto failed;
12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (key_info & WPA_KEY_INFO_SECURE) {
12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_sm_mlme_setprotection(
12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm, sm->bssid, MLME_SETPROTECTION_PROTECT_TYPE_RX,
12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eapol_sm_notify_portValid(sm->eapol, TRUE);
12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE);
12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1216fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	if (sm->group_cipher == WPA_CIPHER_GTK_NOT_USED) {
1217fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		wpa_supplicant_key_neg_complete(sm, sm->bssid,
1218fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt						key_info & WPA_KEY_INFO_SECURE);
1219fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	} else if (ie.gtk &&
12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wpa_supplicant_pairwise_gtk(sm, key,
12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					ie.gtk, ie.gtk_len, key_info) < 0) {
12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"RSN: Failed to configure GTK");
12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ieee80211w_set_keys(sm, &ie) < 0) {
12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"RSN: Failed to configure IGTK");
12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1233cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	if (ie.gtk)
1234cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		wpa_sm_set_rekey_offload(sm);
12351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
12366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (sm->proto == WPA_PROTO_RSN && wpa_key_mgmt_suite_b(sm->key_mgmt)) {
12376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		struct rsn_pmksa_cache_entry *sa;
12386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
12396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		sa = pmksa_cache_add(sm->pmksa, sm->pmk, sm->pmk_len,
1240807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt				     sm->ptk.kck, sm->ptk.kck_len,
12416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				     sm->bssid, sm->own_addr,
12426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				     sm->network_ctx, sm->key_mgmt);
12436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		if (!sm->cur_pmksa)
12446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			sm->cur_pmksa = sa;
12456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
12466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
12474dd28dc25895165566a1c8a9cac7bcd755ff8fe3Dmitry Shmidt	sm->msg_3_of_4_ok = 1;
12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return;
12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfailed:
12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_process_1_of_2_rsn(struct wpa_sm *sm,
12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     const u8 *keydata,
12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     size_t keydatalen,
12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     u16 key_info,
12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     struct wpa_gtk_data *gd)
12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int maxkeylen;
12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_eapol_ie_parse ie;
12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "RSN: msg 1/2 key data", keydata, keydatalen);
12651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (wpa_supplicant_parse_ies(keydata, keydatalen, &ie) < 0)
12661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return -1;
12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: GTK IE in unencrypted key data");
12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie.gtk == NULL) {
12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: No GTK IE in Group Key msg 1/2");
12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	maxkeylen = gd->gtk_len = ie.gtk_len - 2;
12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_supplicant_check_group_cipher(sm, sm->group_cipher,
12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      gd->gtk_len, maxkeylen,
12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      &gd->key_rsc_len, &gd->alg))
12828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "RSN: received GTK in group key handshake",
12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    ie.gtk, ie.gtk_len);
12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gd->keyidx = ie.gtk[0] & 0x3;
12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gd->tx = wpa_supplicant_gtk_tx_bit_workaround(sm,
12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						      !!(ie.gtk[0] & BIT(2)));
12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie.gtk_len - 2 > sizeof(gd->gtk)) {
12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"RSN: Too long GTK in GTK IE (len=%lu)",
12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			(unsigned long) ie.gtk_len - 2);
12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(gd->gtk, ie.gtk + 2, ie.gtk_len - 2);
12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ieee80211w_set_keys(sm, &ie) < 0)
12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"RSN: Failed to configure IGTK");
13008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_process_1_of_2_wpa(struct wpa_sm *sm,
13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     const struct wpa_eapol_key *key,
130743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt					     const u8 *key_data,
130843cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt					     size_t key_data_len, u16 key_info,
130943cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt					     u16 ver, struct wpa_gtk_data *gd)
13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t maxkeylen;
13126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	u16 gtk_len;
13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	gtk_len = WPA_GET_BE16(key->key_length);
131543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	maxkeylen = key_data_len;
13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (maxkeylen < 8) {
13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Too short maxkeylen (%lu)",
13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				(unsigned long) maxkeylen);
13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		maxkeylen -= 8;
13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (gtk_len > maxkeylen ||
13276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	    wpa_supplicant_check_group_cipher(sm, sm->group_cipher,
13286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt					      gtk_len, maxkeylen,
13298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      &gd->key_rsc_len, &gd->alg))
13308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	gd->gtk_len = gtk_len;
13338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gd->keyidx = (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >>
13348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		WPA_KEY_INFO_KEY_INDEX_SHIFT;
1335807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 && sm->ptk.kek_len == 16) {
133661593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		u8 ek[32];
133743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		if (key_data_len > sizeof(gd->gtk)) {
13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
13398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: RC4 key data too long (%lu)",
134043cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt				(unsigned long) key_data_len);
13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
13428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
134361593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		os_memcpy(ek, key->key_iv, 16);
1344807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt		os_memcpy(ek + 16, sm->ptk.kek, sm->ptk.kek_len);
134543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		os_memcpy(gd->gtk, key_data, key_data_len);
134643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		if (rc4_skip(ek, 32, 256, gd->gtk, key_data_len)) {
134761593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt			os_memset(ek, 0, sizeof(ek));
13488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: RC4 failed");
13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
135261593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		os_memset(ek, 0, sizeof(ek));
13538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
135443cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		if (maxkeylen % 8) {
13558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
13568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Unsupported AES-WRAP len %lu",
135743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt				(unsigned long) maxkeylen);
13588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
13598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
13608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (maxkeylen > sizeof(gd->gtk)) {
13618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
13628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: AES-WRAP key data "
13638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"too long (keydatalen=%lu maxkeylen=%lu)",
136443cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt				(unsigned long) key_data_len,
13658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				(unsigned long) maxkeylen);
13668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
13678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1368807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt		if (aes_unwrap(sm->ptk.kek, sm->ptk.kek_len, maxkeylen / 8,
1369807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt			       key_data, gd->gtk)) {
13708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
13718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: AES unwrap failed - could not decrypt "
13728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"GTK");
13738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
13748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
13758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
13768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
13778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: Unsupported key_info type %d", ver);
13788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
13798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	gd->tx = wpa_supplicant_gtk_tx_bit_workaround(
13818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm, !!(key_info & WPA_KEY_INFO_TXRX));
13828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
13848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_send_2_of_2(struct wpa_sm *sm,
13878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      const struct wpa_eapol_key *key,
13888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      int ver, u16 key_info)
13898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1390807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	size_t mic_len, hdrlen, rlen;
13918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_eapol_key *reply;
1392807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	struct wpa_eapol_key_192 *reply192;
1393807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	u8 *rbuf, *key_mic;
13948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1395807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	mic_len = wpa_mic_len(sm->key_mgmt);
1396807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	hdrlen = mic_len == 24 ? sizeof(*reply192) : sizeof(*reply);
13978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
1398807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt				  hdrlen, &rlen, (void *) &reply);
13998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (rbuf == NULL)
14008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1401807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	reply192 = (struct wpa_eapol_key_192 *) reply;
14028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1403f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	reply->type = (sm->proto == WPA_PROTO_RSN ||
1404f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		       sm->proto == WPA_PROTO_OSEN) ?
14058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
14068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key_info &= WPA_KEY_INFO_KEY_INDEX_MASK;
14078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key_info |= ver | WPA_KEY_INFO_MIC | WPA_KEY_INFO_SECURE;
14088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE16(reply->key_info, key_info);
1409f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN)
14108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		WPA_PUT_BE16(reply->key_length, 0);
14118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
14128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(reply->key_length, key->key_length, 2);
14138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(reply->replay_counter, key->replay_counter,
14148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  WPA_REPLAY_COUNTER_LEN);
14158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1416807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	key_mic = reply192->key_mic; /* same offset for reply and reply192 */
1417807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	if (mic_len == 24)
1418807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt		WPA_PUT_BE16(reply192->key_data_length, 0);
1419807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	else
1420807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt		WPA_PUT_BE16(reply->key_data_length, 0);
14218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 2/2");
1423807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver, sm->bssid,
1424807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt			   ETH_P_EAPOL, rbuf, rlen, key_mic);
14258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
14278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
14288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_process_1_of_2(struct wpa_sm *sm,
14318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  const unsigned char *src_addr,
14328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  const struct wpa_eapol_key *key,
143343cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt					  const u8 *key_data,
143443cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt					  size_t key_data_len, u16 ver)
14358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
143643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	u16 key_info;
14378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int rekey, ret;
14388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_gtk_data gd;
14398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14404dd28dc25895165566a1c8a9cac7bcd755ff8fe3Dmitry Shmidt	if (!sm->msg_3_of_4_ok) {
14414dd28dc25895165566a1c8a9cac7bcd755ff8fe3Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
14424dd28dc25895165566a1c8a9cac7bcd755ff8fe3Dmitry Shmidt			"WPA: Group Key Handshake started prior to completion of 4-way handshake");
14434dd28dc25895165566a1c8a9cac7bcd755ff8fe3Dmitry Shmidt		goto failed;
14444dd28dc25895165566a1c8a9cac7bcd755ff8fe3Dmitry Shmidt	}
14454dd28dc25895165566a1c8a9cac7bcd755ff8fe3Dmitry Shmidt
14468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&gd, 0, sizeof(gd));
14478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rekey = wpa_sm_get_state(sm) == WPA_COMPLETED;
14498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: RX message 1 of Group Key "
14508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"Handshake from " MACSTR " (ver=%d)", MAC2STR(src_addr), ver);
14518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key_info = WPA_GET_BE16(key->key_info);
14538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1454f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) {
145543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		ret = wpa_supplicant_process_1_of_2_rsn(sm, key_data,
145643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt							key_data_len, key_info,
14578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							&gd);
14588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
145943cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		ret = wpa_supplicant_process_1_of_2_wpa(sm, key, key_data,
146043cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt							key_data_len,
146143cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt							key_info, ver, &gd);
14628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE);
14658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret)
14678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
14688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_supplicant_install_gtk(sm, &gd, key->key_rsc) ||
14708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wpa_supplicant_send_2_of_2(sm, key, ver, key_info))
14718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto failed;
14726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	os_memset(&gd, 0, sizeof(gd));
14738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (rekey) {
14758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Group rekeying "
14768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"completed with " MACSTR " [GTK=%s]",
14778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(sm->bssid), wpa_cipher_txt(sm->group_cipher));
14788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_sm_cancel_auth_timeout(sm);
14798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_sm_set_state(sm, WPA_COMPLETED);
14808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
14818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_key_neg_complete(sm, sm->bssid,
14828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						key_info &
14838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						WPA_KEY_INFO_SECURE);
14848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1485cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt
1486cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	wpa_sm_set_rekey_offload(sm);
1487cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt
14888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return;
14898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfailed:
14916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	os_memset(&gd, 0, sizeof(gd));
14928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
14938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
14948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_verify_eapol_key_mic(struct wpa_sm *sm,
1497807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt					       struct wpa_eapol_key_192 *key,
14988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       u16 ver,
14998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       const u8 *buf, size_t len)
15008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1501807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN];
15028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ok = 0;
1503807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	size_t mic_len = wpa_mic_len(sm->key_mgmt);
15048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1505807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	os_memcpy(mic, key->key_mic, mic_len);
15068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->tptk_set) {
1507807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt		os_memset(key->key_mic, 0, mic_len);
1508807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt		wpa_eapol_key_mic(sm->tptk.kck, sm->tptk.kck_len, sm->key_mgmt,
1509807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt				  ver, buf, len, key->key_mic);
1510807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt		if (os_memcmp_const(mic, key->key_mic, mic_len) != 0) {
15118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
15128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Invalid EAPOL-Key MIC "
15138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"when using TPTK - ignoring TPTK");
15148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
15158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ok = 1;
15168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->tptk_set = 0;
15178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->ptk_set = 1;
15188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(&sm->ptk, &sm->tptk, sizeof(sm->ptk));
151961593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt			os_memset(&sm->tptk, 0, sizeof(sm->tptk));
15208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
15218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!ok && sm->ptk_set) {
1524807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt		os_memset(key->key_mic, 0, mic_len);
1525807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt		wpa_eapol_key_mic(sm->ptk.kck, sm->ptk.kck_len, sm->key_mgmt,
1526807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt				  ver, buf, len, key->key_mic);
1527807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt		if (os_memcmp_const(mic, key->key_mic, mic_len) != 0) {
15288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
15298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Invalid EAPOL-Key MIC - "
15308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"dropping packet");
15318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
15328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
15338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ok = 1;
15348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!ok) {
15378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
15388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: Could not verify EAPOL-Key MIC - "
15398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"dropping packet");
15408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
15418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(sm->rx_replay_counter, key->replay_counter,
15448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  WPA_REPLAY_COUNTER_LEN);
15458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->rx_replay_counter_set = 1;
15468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
15478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Decrypt RSN EAPOL-Key key data (RC4 or AES-WRAP) */
15518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm,
155243cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt					   struct wpa_eapol_key *key, u16 ver,
155343cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt					   u8 *key_data, size_t *key_data_len)
15548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
15558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "RSN: encrypted key data",
155643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		    key_data, *key_data_len);
15578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!sm->ptk_set) {
15588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
15598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: PTK not available, cannot decrypt EAPOL-Key Key "
15608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Data");
15618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
15628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Decrypt key data here so that this operation does not need
15658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * to be implemented separately for each message type. */
1566807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 && sm->ptk.kek_len == 16) {
15678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		u8 ek[32];
15688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(ek, key->key_iv, 16);
1569807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt		os_memcpy(ek + 16, sm->ptk.kek, sm->ptk.kek_len);
157043cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		if (rc4_skip(ek, 32, 256, key_data, *key_data_len)) {
157161593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt			os_memset(ek, 0, sizeof(ek));
15728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
15738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: RC4 failed");
15748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
15758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
157661593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		os_memset(ek, 0, sizeof(ek));
15778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
1578f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		   ver == WPA_KEY_INFO_TYPE_AES_128_CMAC ||
15796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		   sm->key_mgmt == WPA_KEY_MGMT_OSEN ||
15806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		   wpa_key_mgmt_suite_b(sm->key_mgmt)) {
15818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		u8 *buf;
158243cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		if (*key_data_len < 8 || *key_data_len % 8) {
15838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
158443cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt				"WPA: Unsupported AES-WRAP len %u",
158543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt				(unsigned int) *key_data_len);
15868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
15878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
158843cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		*key_data_len -= 8; /* AES-WRAP adds 8 bytes */
158943cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		buf = os_malloc(*key_data_len);
15908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (buf == NULL) {
15918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
15928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: No memory for AES-UNWRAP buffer");
15938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
15948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1595807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt		if (aes_unwrap(sm->ptk.kek, sm->ptk.kek_len, *key_data_len / 8,
159643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt			       key_data, buf)) {
15978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(buf);
15988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
15998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: AES unwrap failed - "
16008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"could not decrypt EAPOL-Key key data");
16018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
16028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
160343cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		os_memcpy(key_data, buf, *key_data_len);
16048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(buf);
160543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		WPA_PUT_BE16(key->key_data_length, *key_data_len);
16068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
16078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
16088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: Unsupported key_info type %d", ver);
16098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
16108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_key(MSG_DEBUG, "WPA: decrypted EAPOL-Key key data",
161243cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt			key_data, *key_data_len);
16138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
16148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
16158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
16188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_aborted_cached - Notify WPA that PMKSA caching was aborted
16198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
16208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
16218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_aborted_cached(struct wpa_sm *sm)
16228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
16238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm && sm->cur_pmksa) {
16248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
16258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"RSN: Cancelling PMKSA caching attempt");
16268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->cur_pmksa = NULL;
16278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
16298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_eapol_key_dump(struct wpa_sm *sm,
1632807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt			       const struct wpa_eapol_key *key,
1633807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt			       unsigned int key_data_len,
1634807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt			       const u8 *mic, unsigned int mic_len)
16358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
16368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_STDOUT_DEBUG
16378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u16 key_info = WPA_GET_BE16(key->key_info);
16388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "  EAPOL-Key type=%d", key->type);
16408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
16418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"  key_info 0x%x (ver=%d keyidx=%d rsvd=%d %s%s%s%s%s%s%s%s)",
16428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_info, key_info & WPA_KEY_INFO_TYPE_MASK,
16438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		(key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >>
16448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		WPA_KEY_INFO_KEY_INDEX_SHIFT,
16458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		(key_info & (BIT(13) | BIT(14) | BIT(15))) >> 13,
16468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_info & WPA_KEY_INFO_KEY_TYPE ? "Pairwise" : "Group",
16478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_info & WPA_KEY_INFO_INSTALL ? " Install" : "",
16488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_info & WPA_KEY_INFO_ACK ? " Ack" : "",
16498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_info & WPA_KEY_INFO_MIC ? " MIC" : "",
16508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_info & WPA_KEY_INFO_SECURE ? " Secure" : "",
16518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_info & WPA_KEY_INFO_ERROR ? " Error" : "",
16528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_info & WPA_KEY_INFO_REQUEST ? " Request" : "",
16538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		key_info & WPA_KEY_INFO_ENCR_KEY_DATA ? " Encr" : "");
16548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
16558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"  key_length=%u key_data_length=%u",
1656807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt		WPA_GET_BE16(key->key_length), key_data_len);
16578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "  replay_counter",
16588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    key->replay_counter, WPA_REPLAY_COUNTER_LEN);
16598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "  key_nonce", key->key_nonce, WPA_NONCE_LEN);
16608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "  key_iv", key->key_iv, 16);
16618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "  key_rsc", key->key_rsc, 8);
16628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "  key_id (reserved)", key->key_id, 8);
1663807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "  key_mic", mic, mic_len);
16648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_STDOUT_DEBUG */
16658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
16668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
16698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_rx_eapol - Process received WPA EAPOL frames
16708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
16718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @src_addr: Source MAC address of the EAPOL packet
16728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Pointer to the beginning of the EAPOL data (EAPOL header)
16738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Length of the EAPOL frame
16748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 1 = WPA EAPOL-Key processed, 0 = not a WPA EAPOL-Key, -1 failure
16758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
16768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called for each received EAPOL frame. Other than EAPOL-Key
16778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * frames can be skipped if filtering is done elsewhere. wpa_sm_rx_eapol() is
16788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * only processing WPA and WPA2 EAPOL-Key frames.
16798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
16808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * The received EAPOL-Key packets are validated and valid packets are replied
16818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to. In addition, key material (PTK, GTK) is configured at the end of a
16828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * successful key handshake.
16838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
16848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
16858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    const u8 *buf, size_t len)
16868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
168743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	size_t plen, data_len, key_data_len;
168843cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	const struct ieee802_1x_hdr *hdr;
16898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_eapol_key *key;
1690807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	struct wpa_eapol_key_192 *key192;
16918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u16 key_info, ver;
169243cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	u8 *tmp = NULL;
16938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret = -1;
16948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_peerkey *peerkey = NULL;
169543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	u8 *key_data;
1696807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	size_t mic_len, keyhdrlen;
16978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
16998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->ft_completed = 0;
17008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
17018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1702807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	mic_len = wpa_mic_len(sm->key_mgmt);
1703807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	keyhdrlen = mic_len == 24 ? sizeof(*key192) : sizeof(*key);
1704807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt
1705807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	if (len < sizeof(*hdr) + keyhdrlen) {
17068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
17078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: EAPOL frame too short to be a WPA "
17088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"EAPOL-Key (len %lu, expecting at least %lu)",
17098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			(unsigned long) len,
1710807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt			(unsigned long) sizeof(*hdr) + keyhdrlen);
17118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
17128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
171443cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	hdr = (const struct ieee802_1x_hdr *) buf;
17158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	plen = be_to_host16(hdr->length);
17168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data_len = plen + sizeof(*hdr);
17178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
17188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"IEEE 802.1X RX: version=%d type=%d length=%lu",
17198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hdr->version, hdr->type, (unsigned long) plen);
17208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hdr->version < EAPOL_VERSION) {
17228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* TODO: backwards compatibility */
17238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hdr->type != IEEE802_1X_TYPE_EAPOL_KEY) {
17258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
17268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: EAPOL frame (type %u) discarded, "
17278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"not a Key frame", hdr->type);
17288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = 0;
17298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
17308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
173143cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL-Key", buf, len);
1732807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	if (plen > len - sizeof(*hdr) || plen < keyhdrlen) {
17338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
17348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: EAPOL frame payload size %lu "
17358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"invalid (frame size %lu)",
17368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			(unsigned long) plen, (unsigned long) len);
17378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = 0;
17388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
17398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
174043cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	if (data_len < len) {
174143cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
174243cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt			"WPA: ignoring %lu bytes after the IEEE 802.1X data",
174343cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt			(unsigned long) len - data_len);
174443cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	}
174543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt
174643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	/*
174743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	 * Make a copy of the frame since we need to modify the buffer during
174843cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	 * MAC validation and Key Data decryption.
174943cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	 */
175043cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	tmp = os_malloc(data_len);
175143cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	if (tmp == NULL)
175243cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		goto out;
175343cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	os_memcpy(tmp, buf, data_len);
175443cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	key = (struct wpa_eapol_key *) (tmp + sizeof(struct ieee802_1x_hdr));
1755807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	key192 = (struct wpa_eapol_key_192 *)
1756807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt		(tmp + sizeof(struct ieee802_1x_hdr));
1757807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	if (mic_len == 24)
1758807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt		key_data = (u8 *) (key192 + 1);
1759807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	else
1760807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt		key_data = (u8 *) (key + 1);
17618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (key->type != EAPOL_KEY_TYPE_WPA && key->type != EAPOL_KEY_TYPE_RSN)
17638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{
17648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
17658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: EAPOL-Key type (%d) unknown, discarded",
17668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			key->type);
17678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = 0;
17688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
17698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1771807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	if (mic_len == 24)
1772807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt		key_data_len = WPA_GET_BE16(key192->key_data_length);
1773807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	else
1774807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt		key_data_len = WPA_GET_BE16(key->key_data_length);
1775807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	wpa_eapol_key_dump(sm, key, key_data_len, key192->key_mic, mic_len);
1776807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt
1777807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	if (key_data_len > plen - keyhdrlen) {
177843cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Invalid EAPOL-Key "
177943cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt			"frame - key_data overflow (%u > %u)",
178043cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt			(unsigned int) key_data_len,
1781807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt			(unsigned int) (plen - keyhdrlen));
178243cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		goto out;
17838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
178443cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt
178543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt	eapol_sm_notify_lower_layer_success(sm->eapol, 0);
17868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	key_info = WPA_GET_BE16(key->key_info);
17878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ver = key_info & WPA_KEY_INFO_TYPE_MASK;
17888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ver != WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 &&
17898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W)
17908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ver != WPA_KEY_INFO_TYPE_AES_128_CMAC &&
17918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */
1792f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	    ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES &&
17936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	    !wpa_key_mgmt_suite_b(sm->key_mgmt) &&
1794f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	    sm->key_mgmt != WPA_KEY_MGMT_OSEN) {
17958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
17968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: Unsupported EAPOL-Key descriptor version %d",
17978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ver);
17988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
17998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1801f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	if (sm->key_mgmt == WPA_KEY_MGMT_OSEN &&
1802f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	    ver != WPA_KEY_INFO_TYPE_AKM_DEFINED) {
1803f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
1804f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt			"OSEN: Unsupported EAPOL-Key descriptor version %d",
1805f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt			ver);
1806f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		goto out;
1807f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	}
1808f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt
18096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (wpa_key_mgmt_suite_b(sm->key_mgmt) &&
18106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	    ver != WPA_KEY_INFO_TYPE_AKM_DEFINED) {
18116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
18126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			"RSN: Unsupported EAPOL-Key descriptor version %d (expected AKM defined = 0)",
18136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			ver);
18146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		goto out;
18156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
18166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
18178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
18188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_key_mgmt_ft(sm->key_mgmt)) {
18198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* IEEE 802.11r uses a new key_info type (AES-128-CMAC). */
18208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) {
18218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
18228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"FT: AP did not use AES-128-CMAC");
18238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto out;
18248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
18258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
18268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
18278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W
18288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_key_mgmt_sha256(sm->key_mgmt)) {
1829f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC &&
18306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		    sm->key_mgmt != WPA_KEY_MGMT_OSEN &&
18316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		    !wpa_key_mgmt_suite_b(sm->key_mgmt)) {
18328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
18338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: AP did not use the "
18348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"negotiated AES-128-CMAC");
18358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto out;
18368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
18378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
18388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */
18398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->pairwise_cipher == WPA_CIPHER_CCMP &&
18406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	    !wpa_key_mgmt_suite_b(sm->key_mgmt) &&
18418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
18428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
18438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: CCMP is used, but EAPOL-Key "
18448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"descriptor version (%d) is not 2", ver);
18458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->group_cipher != WPA_CIPHER_CCMP &&
18468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    !(key_info & WPA_KEY_INFO_KEY_TYPE)) {
18478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/* Earlier versions of IEEE 802.11i did not explicitly
18488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * require version 2 descriptor for all EAPOL-Key
18498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * packets, so allow group keys to use version 1 if
18508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * CCMP is not used for them. */
18518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
18528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Backwards compatibility: allow invalid "
18538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"version for non-CCMP group keys");
1854658fb4adb9458c3055c64a43833f1a9e89b4db74Jouni Malinen		} else if (ver == WPA_KEY_INFO_TYPE_AES_128_CMAC) {
1855658fb4adb9458c3055c64a43833f1a9e89b4db74Jouni Malinen			wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
1856658fb4adb9458c3055c64a43833f1a9e89b4db74Jouni Malinen				"WPA: Interoperability workaround: allow incorrect (should have been HMAC-SHA1), but stronger (is AES-128-CMAC), descriptor version to be used");
18578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else
18588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto out;
1859717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt	} else if (sm->pairwise_cipher == WPA_CIPHER_GCMP &&
18606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		   !wpa_key_mgmt_suite_b(sm->key_mgmt) &&
1861717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt		   ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
186261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
186361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			"WPA: GCMP is used, but EAPOL-Key "
186461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			"descriptor version (%d) is not 2", ver);
186561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		goto out;
186661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
18678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_PEERKEY
18698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) {
18708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_memcmp(peerkey->addr, src_addr, ETH_ALEN) == 0)
18718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
18728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!(key_info & WPA_KEY_INFO_SMK_MESSAGE) && peerkey) {
18758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!peerkey->initiator && peerkey->replay_counter_set &&
18768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    os_memcmp(key->replay_counter, peerkey->replay_counter,
18778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      WPA_REPLAY_COUNTER_LEN) <= 0) {
18788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
18798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"RSN: EAPOL-Key Replay Counter did not "
18808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"increase (STK) - dropping packet");
18818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto out;
18828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (peerkey->initiator) {
18838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u8 _tmp[WPA_REPLAY_COUNTER_LEN];
18848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(_tmp, key->replay_counter,
18858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  WPA_REPLAY_COUNTER_LEN);
18868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			inc_byte_array(_tmp, WPA_REPLAY_COUNTER_LEN);
18878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (os_memcmp(_tmp, peerkey->replay_counter,
18888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      WPA_REPLAY_COUNTER_LEN) != 0) {
18898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
18908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"RSN: EAPOL-Key Replay "
18918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"Counter did not match (STK) - "
18928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					"dropping packet");
18938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				goto out;
18948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
18958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
18968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (peerkey && peerkey->initiator && (key_info & WPA_KEY_INFO_ACK)) {
18998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
19008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"RSN: Ack bit in key_info from STK peer");
19018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
19028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_PEERKEY */
19048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!peerkey && sm->rx_replay_counter_set &&
19068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(key->replay_counter, sm->rx_replay_counter,
19078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      WPA_REPLAY_COUNTER_LEN) <= 0) {
19088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
19098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: EAPOL-Key Replay Counter did not increase - "
19108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"dropping packet");
19118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
19128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!(key_info & (WPA_KEY_INFO_ACK | WPA_KEY_INFO_SMK_MESSAGE))
19158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_PEERKEY
19168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    && (peerkey == NULL || !peerkey->initiator)
19178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_PEERKEY */
19188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		) {
19198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
19208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: No Ack bit in key_info");
19218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
19228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (key_info & WPA_KEY_INFO_REQUEST) {
19258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
19268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: EAPOL-Key with Request bit - dropped");
19278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
19288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((key_info & WPA_KEY_INFO_MIC) && !peerkey &&
1931807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	    wpa_supplicant_verify_eapol_key_mic(sm, key192, ver, tmp, data_len))
19328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
19338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_PEERKEY
19358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((key_info & WPA_KEY_INFO_MIC) && peerkey &&
1936807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	    peerkey_verify_eapol_key_mic(sm, peerkey, key192, ver, tmp,
1937807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt					 data_len))
19388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
19398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_PEERKEY */
19408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1941f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	if ((sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) &&
19428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
194343cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		if (wpa_supplicant_decrypt_key_data(sm, key, ver, key_data,
194443cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt						    &key_data_len))
19458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto out;
19468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (key_info & WPA_KEY_INFO_KEY_TYPE) {
19498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) {
19508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
19518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: Ignored EAPOL-Key (Pairwise) with "
19528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"non-zero key index");
19538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto out;
19548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
19558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (peerkey) {
19568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/* PeerKey 4-Way Handshake */
1957c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt			peerkey_rx_eapol_4way(sm, peerkey, key, key_info, ver,
1958c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt					      key_data, key_data_len);
19598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (key_info & WPA_KEY_INFO_MIC) {
19608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/* 3/4 4-Way Handshake */
196143cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt			wpa_supplicant_process_3_of_4(sm, key, ver, key_data,
196243cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt						      key_data_len);
19638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
19648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/* 1/4 4-Way Handshake */
19658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_supplicant_process_1_of_4(sm, src_addr, key,
196643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt						      ver, key_data,
196743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt						      key_data_len);
19688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
19698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (key_info & WPA_KEY_INFO_SMK_MESSAGE) {
19708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* PeerKey SMK Handshake */
197143cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt		peerkey_rx_eapol_smk(sm, src_addr, key, key_data_len, key_info,
19728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     ver);
19738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
19748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (key_info & WPA_KEY_INFO_MIC) {
19758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/* 1/2 Group Key Handshake */
19768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_supplicant_process_1_of_2(sm, src_addr, key,
197743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt						      key_data, key_data_len,
197843cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt						      ver);
19798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
19808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
19818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"WPA: EAPOL-Key (Group) without Mic bit - "
19828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"dropped");
19838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
19848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = 1;
19878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtout:
19896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	bin_clear_free(tmp, data_len);
19908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
19918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_CTRL_IFACE
19958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u32 wpa_key_mgmt_suite(struct wpa_sm *sm)
19968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
19978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (sm->key_mgmt) {
19988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_KEY_MGMT_IEEE8021X:
1999f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		return ((sm->proto == WPA_PROTO_RSN ||
2000f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt			 sm->proto == WPA_PROTO_OSEN) ?
20018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			RSN_AUTH_KEY_MGMT_UNSPEC_802_1X :
20028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			WPA_AUTH_KEY_MGMT_UNSPEC_802_1X);
20038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_KEY_MGMT_PSK:
20048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return (sm->proto == WPA_PROTO_RSN ?
20058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X :
20068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X);
20078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
20088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_KEY_MGMT_FT_IEEE8021X:
20098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return RSN_AUTH_KEY_MGMT_FT_802_1X;
20108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_KEY_MGMT_FT_PSK:
20118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return RSN_AUTH_KEY_MGMT_FT_PSK;
20128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
20138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W
20148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_KEY_MGMT_IEEE8021X_SHA256:
20158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return RSN_AUTH_KEY_MGMT_802_1X_SHA256;
20168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_KEY_MGMT_PSK_SHA256:
20178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return RSN_AUTH_KEY_MGMT_PSK_SHA256;
20188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */
2019d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	case WPA_KEY_MGMT_CCKM:
2020d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		return (sm->proto == WPA_PROTO_RSN ?
2021d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			RSN_AUTH_KEY_MGMT_CCKM:
2022d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			WPA_AUTH_KEY_MGMT_CCKM);
20238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_KEY_MGMT_WPA_NONE:
20248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return WPA_AUTH_KEY_MGMT_NONE;
20256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	case WPA_KEY_MGMT_IEEE8021X_SUITE_B:
20266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return RSN_AUTH_KEY_MGMT_802_1X_SUITE_B;
2027807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
2028807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt		return RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192;
20298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
20308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
20318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define RSN_SUITE "%02x-%02x-%02x-%d"
20368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define RSN_SUITE_ARG(s) \
20378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt((s) >> 24) & 0xff, ((s) >> 16) & 0xff, ((s) >> 8) & 0xff, (s) & 0xff
20388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
20408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_get_mib - Dump text list of MIB entries
20418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
20428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Buffer for the list
20438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buflen: Length of the buffer
20448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Number of bytes written to buffer
20458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
20468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used fetch dot11 MIB variables.
20478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
20488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen)
20498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char pmkid_txt[PMKID_LEN * 2 + 1];
20518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int rsna, ret;
20528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
20538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->cur_pmksa) {
20558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_snprintf_hex(pmkid_txt, sizeof(pmkid_txt),
20568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 sm->cur_pmksa->pmkid, PMKID_LEN);
20578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else
20588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pmkid_txt[0] = '\0';
20598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((wpa_key_mgmt_wpa_psk(sm->key_mgmt) ||
20618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt)) &&
20628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    sm->proto == WPA_PROTO_RSN)
20638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		rsna = 1;
20648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
20658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		rsna = 0;
20668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = os_snprintf(buf, buflen,
20688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dot11RSNAOptionImplemented=TRUE\n"
20698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dot11RSNAPreauthenticationImplemented=TRUE\n"
20708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dot11RSNAEnabled=%s\n"
20718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dot11RSNAPreauthenticationEnabled=%s\n"
20728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dot11RSNAConfigVersion=%d\n"
20738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dot11RSNAConfigPairwiseKeysSupported=5\n"
20748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dot11RSNAConfigGroupCipherSize=%d\n"
20758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dot11RSNAConfigPMKLifetime=%d\n"
20768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dot11RSNAConfigPMKReauthThreshold=%d\n"
20778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dot11RSNAConfigNumberOfPTKSAReplayCounters=1\n"
20788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "dot11RSNAConfigSATimeout=%d\n",
20798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  rsna ? "TRUE" : "FALSE",
20808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  rsna ? "TRUE" : "FALSE",
20818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  RSN_VERSION,
20824530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt			  wpa_cipher_key_len(sm->group_cipher) * 8,
20838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sm->dot11RSNAConfigPMKLifetime,
20848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sm->dot11RSNAConfigPMKReauthThreshold,
20858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  sm->dot11RSNAConfigSATimeout);
20866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (os_snprintf_error(buflen, ret))
20878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
20888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = ret;
20898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = os_snprintf(
20918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		buf + len, buflen - len,
20928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"dot11RSNAAuthenticationSuiteSelected=" RSN_SUITE "\n"
20938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"dot11RSNAPairwiseCipherSelected=" RSN_SUITE "\n"
20948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"dot11RSNAGroupCipherSelected=" RSN_SUITE "\n"
20958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"dot11RSNAPMKIDUsed=%s\n"
20968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"dot11RSNAAuthenticationSuiteRequested=" RSN_SUITE "\n"
20978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"dot11RSNAPairwiseCipherRequested=" RSN_SUITE "\n"
20988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"dot11RSNAGroupCipherRequested=" RSN_SUITE "\n"
20998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"dot11RSNAConfigNumberOfGTKSAReplayCounters=0\n"
21008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"dot11RSNA4WayHandshakeFailures=%u\n",
21018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		RSN_SUITE_ARG(wpa_key_mgmt_suite(sm)),
21024530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		RSN_SUITE_ARG(wpa_cipher_to_suite(sm->proto,
21034530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt						  sm->pairwise_cipher)),
21044530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		RSN_SUITE_ARG(wpa_cipher_to_suite(sm->proto,
21054530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt						  sm->group_cipher)),
21068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pmkid_txt,
21078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		RSN_SUITE_ARG(wpa_key_mgmt_suite(sm)),
21084530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		RSN_SUITE_ARG(wpa_cipher_to_suite(sm->proto,
21094530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt						  sm->pairwise_cipher)),
21104530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt		RSN_SUITE_ARG(wpa_cipher_to_suite(sm->proto,
21114530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt						  sm->group_cipher)),
21128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->dot11RSNA4WayHandshakeFailures);
21136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (!os_snprintf_error(buflen - len, ret))
21148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len += ret;
21158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return (int) len;
21178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_CTRL_IFACE */
21198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_sm_pmksa_free_cb(struct rsn_pmksa_cache_entry *entry,
2122d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				 void *ctx, enum pmksa_free_reason reason)
21238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_sm *sm = ctx;
2125d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	int deauth = 0;
2126d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
2127d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: PMKSA cache entry free_cb: "
2128d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		MACSTR " reason=%d", MAC2STR(entry->aa), reason);
2129d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
2130d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (sm->cur_pmksa == entry) {
2131d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
2132d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			"RSN: %s current PMKSA entry",
2133d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			reason == PMKSA_REPLACE ? "replaced" : "removed");
2134d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		pmksa_cache_clear_current(sm);
2135d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
2136d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		/*
2137d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		 * If an entry is simply being replaced, there's no need to
2138d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		 * deauthenticate because it will be immediately re-added.
2139d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		 * This happens when EAP authentication is completed again
2140d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		 * (reauth or failed PMKSA caching attempt).
2141d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		 */
2142d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		if (reason != PMKSA_REPLACE)
2143d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			deauth = 1;
2144d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	}
21458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2146d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (reason == PMKSA_EXPIRE &&
21478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (sm->pmk_len == entry->pmk_len &&
21488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     os_memcmp(sm->pmk, entry->pmk, sm->pmk_len) == 0)) {
21498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
2150d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			"RSN: deauthenticating due to expired PMK");
2151d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		pmksa_cache_clear_current(sm);
2152d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		deauth = 1;
2153d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	}
21548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2155d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (deauth) {
21568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(sm->pmk, 0, sizeof(sm->pmk));
21578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
21588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
21638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_init - Initialize WPA state machine
21648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ctx: Context pointer for callbacks; this needs to be an allocated buffer
21658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the allocated WPA state machine data
21668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
21678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used to allocate a new WPA state machine and the returned
21688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * value is passed to all WPA state machine calls.
21698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
21708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_sm * wpa_sm_init(struct wpa_sm_ctx *ctx)
21718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
21728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_sm *sm;
21738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm = os_zalloc(sizeof(*sm));
21758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
21768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
21778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_init(&sm->pmksa_candidates);
21788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->renew_snonce = 1;
21798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->ctx = ctx;
21808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->dot11RSNAConfigPMKLifetime = 43200;
21828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->dot11RSNAConfigPMKReauthThreshold = 70;
21838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->dot11RSNAConfigSATimeout = 60;
21848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->pmksa = pmksa_cache_init(wpa_sm_pmksa_free_cb, sm, sm);
21868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->pmksa == NULL) {
21878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
21888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"RSN: PMKSA cache initialization failed");
21898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(sm);
21908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
21918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return sm;
21948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
21958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
21988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_deinit - Deinitialize WPA state machine
21998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
22008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
22018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_deinit(struct wpa_sm *sm)
22028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
22048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
22058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pmksa_cache_deinit(sm->pmksa);
22068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(wpa_sm_start_preauth, sm, NULL);
22078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL);
22088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sm->assoc_wpa_ie);
22098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sm->ap_wpa_ie);
22108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sm->ap_rsn_ie);
22116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	wpa_sm_drop_sa(sm);
22128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sm->ctx);
22138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	peerkey_deinit(sm);
22148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
22158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sm->assoc_resp_ies);
22168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
22178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sm);
22188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
22228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_notify_assoc - Notify WPA state machine about association
22238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
22248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @bssid: The BSSID of the new association
22258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
22268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called to let WPA state machine know that the connection
22278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * was established.
22288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
22298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid)
22308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int clear_ptk = 1;
22328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
22348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
22358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
22378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"WPA: Association event - clear replay counter");
22388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(sm->bssid, bssid, ETH_ALEN);
22398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(sm->rx_replay_counter, 0, WPA_REPLAY_COUNTER_LEN);
22408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->rx_replay_counter_set = 0;
22418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->renew_snonce = 1;
22428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(sm->preauth_bssid, bssid, ETH_ALEN) == 0)
22438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		rsn_preauth_deinit(sm);
22448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
22468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_ft_is_completed(sm)) {
22478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
22488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Clear portValid to kick EAPOL state machine to re-enter
22498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * AUTHENTICATED state to get the EAPOL port Authorized.
22508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
22518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eapol_sm_notify_portValid(sm->eapol, FALSE);
22528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_key_neg_complete(sm, sm->bssid, 1);
22538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Prepare for the next transition */
22558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_ft_prepare_auth_request(sm, NULL);
22568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		clear_ptk = 0;
22588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
22608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (clear_ptk) {
22628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
22638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * IEEE 802.11, 8.4.10: Delete PTK SA on (re)association if
22648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * this is not part of a Fast BSS Transition.
22658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
22668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Clear old PTK");
22678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->ptk_set = 0;
226861593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		os_memset(&sm->ptk, 0, sizeof(sm->ptk));
22698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->tptk_set = 0;
227061593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		os_memset(&sm->tptk, 0, sizeof(sm->tptk));
22718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
22728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS
22748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_tdls_assoc(sm);
22758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS */
2276cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
2277cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#ifdef CONFIG_P2P
2278cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	os_memset(sm->p2p_ip_addr, 0, sizeof(sm->p2p_ip_addr));
2279cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#endif /* CONFIG_P2P */
22808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
22848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_notify_disassoc - Notify WPA state machine about disassociation
22858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
22868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
22878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called to let WPA state machine know that the connection
22888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * was lost. This will abort any existing pre-authentication session.
22898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
22908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_notify_disassoc(struct wpa_sm *sm)
22918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22924dd28dc25895165566a1c8a9cac7bcd755ff8fe3Dmitry Shmidt	eloop_cancel_timeout(wpa_sm_start_preauth, sm, NULL);
22934dd28dc25895165566a1c8a9cac7bcd755ff8fe3Dmitry Shmidt	eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL);
2294fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	peerkey_deinit(sm);
22958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rsn_preauth_deinit(sm);
2296d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	pmksa_cache_clear_current(sm);
22978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_sm_get_state(sm) == WPA_4WAY_HANDSHAKE)
22988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->dot11RSNA4WayHandshakeFailures++;
22998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS
23008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_tdls_disassoc(sm);
23018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS */
23026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
23036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	/* Keys are not needed in the WPA state machine anymore */
23046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	wpa_sm_drop_sa(sm);
23054dd28dc25895165566a1c8a9cac7bcd755ff8fe3Dmitry Shmidt
23064dd28dc25895165566a1c8a9cac7bcd755ff8fe3Dmitry Shmidt	sm->msg_3_of_4_ok = 0;
23078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
23118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_pmk - Set PMK
23128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
23138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pmk: The new PMK
23148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pmk_len: The length of the new PMK in bytes
23156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * @bssid: AA to add into PMKSA cache or %NULL to not cache the PMK
23168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
23178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Configure the PMK for WPA state machine.
23188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
23196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtvoid wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len,
23206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		    const u8 *bssid)
23218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
23238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
23248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->pmk_len = pmk_len;
23268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(sm->pmk, pmk, pmk_len);
23278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
23298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Set XXKey to be PSK for FT key derivation */
23308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->xxkey_len = pmk_len;
23318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(sm->xxkey, pmk, pmk_len);
23328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
23336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
23346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (bssid) {
23356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		pmksa_cache_add(sm->pmksa, pmk, pmk_len, NULL, 0,
23366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				bssid, sm->own_addr,
23376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt				sm->network_ctx, sm->key_mgmt);
23386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
23398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
23438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_pmk_from_pmksa - Set PMK based on the current PMKSA
23448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
23458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
23468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Take the PMK from the current PMKSA into use. If no PMKSA is active, the PMK
23478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * will be cleared.
23488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
23498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_set_pmk_from_pmksa(struct wpa_sm *sm)
23508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
23528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
23538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->cur_pmksa) {
23558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->pmk_len = sm->cur_pmksa->pmk_len;
23568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(sm->pmk, sm->cur_pmksa->pmk, sm->pmk_len);
23578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
23588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->pmk_len = PMK_LEN;
23598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(sm->pmk, 0, PMK_LEN);
23608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
23618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
23658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_fast_reauth - Set fast reauthentication (EAP) enabled/disabled
23668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
23678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @fast_reauth: Whether fast reauthentication (EAP) is allowed
23688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
23698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_set_fast_reauth(struct wpa_sm *sm, int fast_reauth)
23708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm)
23728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->fast_reauth = fast_reauth;
23738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
23778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_scard_ctx - Set context pointer for smartcard callbacks
23788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
23798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @scard_ctx: Context pointer for smartcard related callback functions
23808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
23818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_set_scard_ctx(struct wpa_sm *sm, void *scard_ctx)
23828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
23848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
23858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->scard_ctx = scard_ctx;
23868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->preauth_eapol)
23878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eapol_sm_register_scard_ctx(sm->preauth_eapol, scard_ctx);
23888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
23928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_config - Notification of current configration change
23938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
23948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @config: Pointer to current network configuration
23958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
23968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Notify WPA state machine that configuration has changed. config will be
23978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * stored as a backpointer to network configuration. This can be %NULL to clear
23988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the stored pointed.
23998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
24008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_set_config(struct wpa_sm *sm, struct rsn_supp_config *config)
24018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!sm)
24038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
24048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config) {
24068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->network_ctx = config->network_ctx;
24078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->peerkey_enabled = config->peerkey_enabled;
24088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->allowed_pairwise_cipher = config->allowed_pairwise_cipher;
24098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->proactive_key_caching = config->proactive_key_caching;
24108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eap_workaround = config->eap_workaround;
24118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eap_conf_ctx = config->eap_conf_ctx;
24128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (config->ssid) {
24138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(sm->ssid, config->ssid, config->ssid_len);
24148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->ssid_len = config->ssid_len;
24158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else
24168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->ssid_len = 0;
24178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->wpa_ptk_rekey = config->wpa_ptk_rekey;
2418cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		sm->p2p = config->p2p;
24198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
24208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->network_ctx = NULL;
24218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->peerkey_enabled = 0;
24228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->allowed_pairwise_cipher = 0;
24238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->proactive_key_caching = 0;
24248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eap_workaround = 0;
24258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eap_conf_ctx = NULL;
24268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->ssid_len = 0;
24278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->wpa_ptk_rekey = 0;
2428cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		sm->p2p = 0;
24298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
24348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_own_addr - Set own MAC address
24358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
24368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: Own MAC address
24378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
24388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_set_own_addr(struct wpa_sm *sm, const u8 *addr)
24398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm)
24418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(sm->own_addr, addr, ETH_ALEN);
24428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
24468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_ifname - Set network interface name
24478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
24488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ifname: Interface name
24498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @bridge_ifname: Optional bridge interface name (for pre-auth)
24508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
24518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_set_ifname(struct wpa_sm *sm, const char *ifname,
24528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       const char *bridge_ifname)
24538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm) {
24558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->ifname = ifname;
24568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->bridge_ifname = bridge_ifname;
24578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
24628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_eapol - Set EAPOL state machine pointer
24638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
24648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @eapol: Pointer to EAPOL state machine allocated with eapol_sm_init()
24658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
24668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_set_eapol(struct wpa_sm *sm, struct eapol_sm *eapol)
24678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm)
24698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->eapol = eapol;
24708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
24748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_param - Set WPA state machine parameters
24758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
24768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @param: Parameter field
24778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @value: Parameter value
24788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
24798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
24808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param,
24818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     unsigned int value)
24828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret = 0;
24848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
24868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
24878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (param) {
24898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case RSNA_PMK_LIFETIME:
24908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (value > 0)
24918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->dot11RSNAConfigPMKLifetime = value;
24928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
24938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = -1;
24948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
24958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case RSNA_PMK_REAUTH_THRESHOLD:
24968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (value > 0 && value <= 100)
24978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->dot11RSNAConfigPMKReauthThreshold = value;
24988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
24998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = -1;
25008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
25018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case RSNA_SA_TIMEOUT:
25028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (value > 0)
25038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->dot11RSNAConfigSATimeout = value;
25048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
25058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ret = -1;
25068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
25078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_PARAM_PROTO:
25088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->proto = value;
25098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
25108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_PARAM_PAIRWISE:
25118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->pairwise_cipher = value;
25128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
25138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_PARAM_GROUP:
25148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->group_cipher = value;
25158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
25168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_PARAM_KEY_MGMT:
25178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->key_mgmt = value;
25188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
25198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W
25208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_PARAM_MGMT_GROUP:
25218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->mgmt_group_cipher = value;
25228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
25238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */
25248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_PARAM_RSN_ENABLED:
25258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->rsn_enabled = value;
25268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
25278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case WPA_PARAM_MFP:
25288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->mfp = value;
25298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
25308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
25318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
25328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
25358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
25398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_get_status - Get WPA state machine
25408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
25418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Buffer for status information
25428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buflen: Maximum buffer length
25438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @verbose: Whether to include verbose status information
25448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Number of bytes written to buf.
25458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
25468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Query WPA state machine for status information. This function fills in
25478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * a text area with current status information. If the buffer (buf) is not
25488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * large enough, status information will be truncated to fit the buffer.
25498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
25508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_get_status(struct wpa_sm *sm, char *buf, size_t buflen,
25518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      int verbose)
25528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *pos = buf, *end = buf + buflen;
25548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
25558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = os_snprintf(pos, end - pos,
25578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "pairwise_cipher=%s\n"
25588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "group_cipher=%s\n"
25598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  "key_mgmt=%s\n",
25608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  wpa_cipher_txt(sm->pairwise_cipher),
25618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  wpa_cipher_txt(sm->group_cipher),
25628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  wpa_key_mgmt_txt(sm->key_mgmt, sm->proto));
25636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (os_snprintf_error(end - pos, ret))
25648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return pos - buf;
25658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += ret;
2566d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
2567d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (sm->mfp != NO_MGMT_FRAME_PROTECTION && sm->ap_rsn_ie) {
2568d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		struct wpa_ie_data rsn;
2569d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		if (wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, &rsn)
2570d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		    >= 0 &&
2571d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		    rsn.capabilities & (WPA_CAPABILITY_MFPR |
2572d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt					WPA_CAPABILITY_MFPC)) {
2573d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			ret = os_snprintf(pos, end - pos, "pmf=%d\n",
2574d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt					  (rsn.capabilities &
2575d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt					   WPA_CAPABILITY_MFPR) ? 2 : 1);
25766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt			if (os_snprintf_error(end - pos, ret))
2577d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				return pos - buf;
2578d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			pos += ret;
2579d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		}
2580d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	}
2581d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
25828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return pos - buf;
25838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2586f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidtint wpa_sm_pmf_enabled(struct wpa_sm *sm)
2587f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt{
2588f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt	struct wpa_ie_data rsn;
2589f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt
2590f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt	if (sm->mfp == NO_MGMT_FRAME_PROTECTION || !sm->ap_rsn_ie)
2591f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt		return 0;
2592f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt
2593f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt	if (wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, &rsn) >= 0 &&
2594f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt	    rsn.capabilities & (WPA_CAPABILITY_MFPR | WPA_CAPABILITY_MFPC))
2595f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt		return 1;
2596f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt
2597f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt	return 0;
2598f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt}
2599f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt
2600f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt
26018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
26028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_assoc_wpa_ie_default - Generate own WPA/RSN IE from configuration
26038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
26048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_ie: Pointer to buffer for WPA/RSN IE
26058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_ie_len: Pointer to the length of the wpa_ie buffer
26068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
26078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
26088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_set_assoc_wpa_ie_default(struct wpa_sm *sm, u8 *wpa_ie,
26098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    size_t *wpa_ie_len)
26108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
26128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
26148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
26158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = wpa_gen_wpa_ie(sm, wpa_ie, *wpa_ie_len);
26178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0)
26188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
26198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*wpa_ie_len = res;
26208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "WPA: Set own WPA IE default",
26228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    wpa_ie, *wpa_ie_len);
26238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->assoc_wpa_ie == NULL) {
26258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
26268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Make a copy of the WPA/RSN IE so that 4-Way Handshake gets
26278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * the correct version of the IE even if PMKSA caching is
26288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * aborted (which would remove PMKID from IE generation).
26298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
26308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->assoc_wpa_ie = os_malloc(*wpa_ie_len);
26318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->assoc_wpa_ie == NULL)
26328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
26338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(sm->assoc_wpa_ie, wpa_ie, *wpa_ie_len);
26358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->assoc_wpa_ie_len = *wpa_ie_len;
26368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
26398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
26438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_assoc_wpa_ie - Set own WPA/RSN IE from (Re)AssocReq
26448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
26458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ie: Pointer to IE data (starting from id)
26468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: IE length
26478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
26488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
26498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Inform WPA state machine about the WPA/RSN IE used in (Re)Association
26508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Request frame. The IE will be used to override the default value generated
26518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * with wpa_sm_set_assoc_wpa_ie_default().
26528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
26538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_set_assoc_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len)
26548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
26568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
26578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sm->assoc_wpa_ie);
26598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie == NULL || len == 0) {
26608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
26618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: clearing own WPA/RSN IE");
26628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->assoc_wpa_ie = NULL;
26638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->assoc_wpa_ie_len = 0;
26648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
26658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "WPA: set own WPA/RSN IE", ie, len);
26668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->assoc_wpa_ie = os_malloc(len);
26678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->assoc_wpa_ie == NULL)
26688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
26698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(sm->assoc_wpa_ie, ie, len);
26718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->assoc_wpa_ie_len = len;
26728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
26738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
26758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
26768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
26798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_ap_wpa_ie - Set AP WPA IE from Beacon/ProbeResp
26808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
26818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ie: Pointer to IE data (starting from id)
26828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: IE length
26838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
26848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
26858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Inform WPA state machine about the WPA IE used in Beacon / Probe Response
26868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * frame.
26878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
26888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_set_ap_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len)
26898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
26908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
26918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
26928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sm->ap_wpa_ie);
26948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie == NULL || len == 0) {
26958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
26968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: clearing AP WPA IE");
26978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->ap_wpa_ie = NULL;
26988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->ap_wpa_ie_len = 0;
26998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
27008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "WPA: set AP WPA IE", ie, len);
27018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->ap_wpa_ie = os_malloc(len);
27028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->ap_wpa_ie == NULL)
27038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
27048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(sm->ap_wpa_ie, ie, len);
27068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->ap_wpa_ie_len = len;
27078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
27108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
27148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_set_ap_rsn_ie - Set AP RSN IE from Beacon/ProbeResp
27158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
27168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ie: Pointer to IE data (starting from id)
27178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: IE length
27188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
27198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
27208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Inform WPA state machine about the RSN IE used in Beacon / Probe Response
27218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * frame.
27228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
27238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, size_t len)
27248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
27268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
27278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(sm->ap_rsn_ie);
27298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ie == NULL || len == 0) {
27308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
27318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: clearing AP RSN IE");
27328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->ap_rsn_ie = NULL;
27338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->ap_rsn_ie_len = 0;
27348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
27358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "WPA: set AP RSN IE", ie, len);
27368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->ap_rsn_ie = os_malloc(len);
27378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->ap_rsn_ie == NULL)
27388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
27398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(sm->ap_rsn_ie, ie, len);
27418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sm->ap_rsn_ie_len = len;
27428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
27458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
27498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_sm_parse_own_wpa_ie - Parse own WPA/RSN IE
27508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init()
27518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Pointer to data area for parsing results
27528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 if IE is not known, or -2 on parsing failure
27538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
27548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Parse the contents of the own WPA or RSN IE from (Re)AssocReq and write the
27558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * parsed data into data.
27568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
27578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_parse_own_wpa_ie(struct wpa_sm *sm, struct wpa_ie_data *data)
27588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
27608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
27618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->assoc_wpa_ie == NULL) {
27638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
27648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"WPA: No WPA/RSN IE available from association info");
27658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
27668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
27678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_parse_wpa_ie(sm->assoc_wpa_ie, sm->assoc_wpa_ie_len, data))
27688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -2;
27698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
27708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_pmksa_cache_list(struct wpa_sm *sm, char *buf, size_t len)
27748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return pmksa_cache_list(sm->pmksa, buf, len);
27768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_sm_drop_sa(struct wpa_sm *sm)
27808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Clear old PMK and PTK");
27828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->ptk_set = 0;
27838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sm->tptk_set = 0;
27848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(sm->pmk, 0, sizeof(sm->pmk));
27858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&sm->ptk, 0, sizeof(sm->ptk));
27868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&sm->tptk, 0, sizeof(sm->tptk));
27876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#ifdef CONFIG_IEEE80211R
27886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	os_memset(sm->xxkey, 0, sizeof(sm->xxkey));
27896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	os_memset(sm->pmk_r0, 0, sizeof(sm->pmk_r0));
27906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	os_memset(sm->pmk_r1, 0, sizeof(sm->pmk_r1));
27916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif /* CONFIG_IEEE80211R */
27928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
27938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
27958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_sm_has_ptk(struct wpa_sm *sm)
27968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
27978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm == NULL)
27988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
27998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return sm->ptk_set;
28008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
28011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
28021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
28031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtvoid wpa_sm_update_replay_ctr(struct wpa_sm *sm, const u8 *replay_ctr)
28041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
28051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	os_memcpy(sm->rx_replay_counter, replay_ctr, WPA_REPLAY_COUNTER_LEN);
28061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
28071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
28081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
28091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtvoid wpa_sm_pmksa_cache_flush(struct wpa_sm *sm, void *network_ctx)
28101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
2811f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt	pmksa_cache_flush(sm->pmksa, network_ctx, NULL, 0);
28121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
281361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
281461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
2815a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt#ifdef CONFIG_WNM
281661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 subelem_id, u8 *buf)
281761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
281861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	u16 keyinfo;
281961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	u8 keylen;  /* plaintext key len */
282061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	u8 *key_rsc;
282161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
282261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (subelem_id == WNM_SLEEP_SUBELEM_GTK) {
282361593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		struct wpa_gtk_data gd;
282461593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt
282561593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		os_memset(&gd, 0, sizeof(gd));
282661593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		keylen = wpa_cipher_key_len(sm->group_cipher);
282761593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		gd.key_rsc_len = wpa_cipher_rsc_len(sm->group_cipher);
282861593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		gd.alg = wpa_cipher_to_alg(sm->group_cipher);
282961593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		if (gd.alg == WPA_ALG_NONE) {
283061593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt			wpa_printf(MSG_DEBUG, "Unsupported group cipher suite");
283161593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt			return -1;
283261593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		}
283361593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt
283461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		key_rsc = buf + 5;
2835a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		keyinfo = WPA_GET_LE16(buf + 2);
283661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		gd.gtk_len = keylen;
283761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (gd.gtk_len != buf[4]) {
283861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpa_printf(MSG_DEBUG, "GTK len mismatch len %d vs %d",
283961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				   gd.gtk_len, buf[4]);
284061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
284161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
284261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		gd.keyidx = keyinfo & 0x03; /* B0 - B1 */
284361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		gd.tx = wpa_supplicant_gtk_tx_bit_workaround(
284461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		         sm, !!(keyinfo & WPA_KEY_INFO_TXRX));
284561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
2846a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		os_memcpy(gd.gtk, buf + 13, gd.gtk_len);
284761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
284861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpa_hexdump_key(MSG_DEBUG, "Install GTK (WNM SLEEP)",
284961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				gd.gtk, gd.gtk_len);
285061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (wpa_supplicant_install_gtk(sm, &gd, key_rsc)) {
285161593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt			os_memset(&gd, 0, sizeof(gd));
285261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpa_printf(MSG_DEBUG, "Failed to install the GTK in "
285361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				   "WNM mode");
285461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
285561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
285661593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		os_memset(&gd, 0, sizeof(gd));
285761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_IEEE80211W
285861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else if (subelem_id == WNM_SLEEP_SUBELEM_IGTK) {
285961593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		struct wpa_igtk_kde igd;
286061593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		u16 keyidx;
286161593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt
286261593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		os_memset(&igd, 0, sizeof(igd));
2863b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt		keylen = wpa_cipher_key_len(sm->mgmt_group_cipher);
286461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		os_memcpy(igd.keyid, buf + 2, 2);
286561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		os_memcpy(igd.pn, buf + 4, 6);
286661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
286761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		keyidx = WPA_GET_LE16(igd.keyid);
2868b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt		os_memcpy(igd.igtk, buf + 10, keylen);
286961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
287061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpa_hexdump_key(MSG_DEBUG, "Install IGTK (WNM SLEEP)",
2871b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt				igd.igtk, keylen);
2872b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt		if (wpa_sm_set_key(sm, wpa_cipher_to_alg(sm->mgmt_group_cipher),
2873b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt				   broadcast_ether_addr,
287461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				   keyidx, 0, igd.pn, sizeof(igd.pn),
2875b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt				   igd.igtk, keylen) < 0) {
287661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpa_printf(MSG_DEBUG, "Failed to install the IGTK in "
287761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				   "WNM mode");
287861593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt			os_memset(&igd, 0, sizeof(igd));
287961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
288061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
288161593f02176862f4880ddefcb1f54cb5f5d9f043Dmitry Shmidt		os_memset(&igd, 0, sizeof(igd));
288261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_IEEE80211W */
288361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else {
288461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpa_printf(MSG_DEBUG, "Unknown element id");
288561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return -1;
288661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
288761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
288861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
288961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
2890a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt#endif /* CONFIG_WNM */
2891fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt
2892fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt
2893fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt#ifdef CONFIG_PEERKEY
2894fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidtint wpa_sm_rx_eapol_peerkey(struct wpa_sm *sm, const u8 *src_addr,
2895fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			    const u8 *buf, size_t len)
2896fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt{
2897fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	struct wpa_peerkey *peerkey;
2898fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt
2899fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) {
2900fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		if (os_memcmp(peerkey->addr, src_addr, ETH_ALEN) == 0)
2901fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			break;
2902fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	}
2903fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt
2904fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	if (!peerkey)
2905fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		return 0;
2906fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt
2907fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	wpa_sm_rx_eapol(sm, src_addr, buf, len);
2908fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt
2909fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	return 1;
2910fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt}
2911fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt#endif /* CONFIG_PEERKEY */
2912cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
2913cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
2914cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#ifdef CONFIG_P2P
2915cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
2916cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtint wpa_sm_get_p2p_ip_addr(struct wpa_sm *sm, u8 *buf)
2917cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt{
2918cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (sm == NULL || WPA_GET_BE32(sm->p2p_ip_addr) == 0)
2919cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		return -1;
2920cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	os_memcpy(buf, sm->p2p_ip_addr, 3 * 4);
2921cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	return 0;
2922cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt}
2923cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
2924cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#endif /* CONFIG_P2P */
29256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
29266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
29276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtvoid wpa_sm_set_rx_replay_ctr(struct wpa_sm *sm, const u8 *rx_replay_counter)
29286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
29296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	if (rx_replay_counter == NULL)
29306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		return;
29316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
29326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	os_memcpy(sm->rx_replay_counter, rx_replay_counter,
29336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		  WPA_REPLAY_COUNTER_LEN);
29346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	sm->rx_replay_counter_set = 1;
29356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	wpa_printf(MSG_DEBUG, "Updated key replay counter");
29366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
29376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
29386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt
2939807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidtvoid wpa_sm_set_ptk_kck_kek(struct wpa_sm *sm,
2940807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt			    const u8 *ptk_kck, size_t ptk_kck_len,
2941807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt			    const u8 *ptk_kek, size_t ptk_kek_len)
29426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{
2943807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	if (ptk_kck && ptk_kck_len <= WPA_KCK_MAX_LEN) {
2944807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt		os_memcpy(sm->ptk.kck, ptk_kck, ptk_kck_len);
2945807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt		sm->ptk.kck_len = ptk_kck_len;
29466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_DEBUG, "Updated PTK KCK");
29476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
2948807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt	if (ptk_kek && ptk_kek_len <= WPA_KEK_MAX_LEN) {
2949807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt		os_memcpy(sm->ptk.kek, ptk_kek, ptk_kek_len);
2950807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt		sm->ptk.kek_len = ptk_kek_len;
29516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt		wpa_printf(MSG_DEBUG, "Updated PTK KEK");
29526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	}
29536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt	sm->ptk_set = 1;
29546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt}
2955