18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd - PeerKey for Direct Link Setup (DLS)
38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2006-2009, 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 "utils/includes.h"
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/common.h"
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/eloop.h"
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/sha1.h"
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/sha256.h"
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/random.h"
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_auth.h"
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_auth_i.h"
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_auth_ie.h"
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_PEERKEY
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_stsl_step(void *eloop_ctx, void *timeout_ctx)
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if 0
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_authenticator *wpa_auth = eloop_ctx;
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_stsl_negotiation *neg = timeout_ctx;
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: ? */
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_stsl_search {
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *addr;
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_state_machine *sm;
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_stsl_select_sta(struct wpa_state_machine *sm, void *ctx)
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_stsl_search *search = ctx;
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(search->addr, sm->addr, ETH_ALEN) == 0) {
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		search->sm = sm;
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_smk_send_error(struct wpa_authenticator *wpa_auth,
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       struct wpa_state_machine *sm, const u8 *peer,
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       u16 mui, u16 error_type)
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 kde[2 + RSN_SELECTOR_LEN + ETH_ALEN +
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       2 + RSN_SELECTOR_LEN + sizeof(struct rsn_error_kde)];
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *pos;
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct rsn_error_kde error;
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Sending SMK Error");
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = kde;
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (peer) {
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN,
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  NULL, 0);
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	error.mui = host_to_be16(mui);
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	error.error_type = host_to_be16(error_type);
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = wpa_add_kde(pos, RSN_KEY_DATA_ERROR,
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  (u8 *) &error, sizeof(error), NULL, 0);
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	__wpa_send_eapol(wpa_auth, sm,
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_ERROR,
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 NULL, NULL, kde, pos - kde, 0, 0, 0);
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_smk_m1(struct wpa_authenticator *wpa_auth,
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct wpa_state_machine *sm, struct wpa_eapol_key *key)
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_eapol_ie_parse kde;
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_stsl_search search;
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *buf, *pos;
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t buf_len;
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_parse_kde_ies((const u8 *) (key + 1),
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      WPA_GET_BE16(key->key_data_length), &kde) < 0) {
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M1");
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (kde.rsn_ie == NULL || kde.mac_addr == NULL ||
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    kde.mac_addr_len < ETH_ALEN) {
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "RSN: No RSN IE or MAC address KDE in "
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "SMK M1");
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Initiator = sm->addr; Peer = kde.mac_addr */
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	search.addr = kde.mac_addr;
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	search.sm = NULL;
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_auth_for_each_sta(wpa_auth, wpa_stsl_select_sta, &search) ==
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    0 || search.sm == NULL) {
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "RSN: SMK handshake with " MACSTR
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   " aborted - STA not associated anymore",
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   MAC2STR(kde.mac_addr));
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_smk_send_error(wpa_auth, sm, kde.mac_addr, STK_MUI_SMK,
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   STK_ERR_STA_NR);
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* FIX: wpa_stsl_remove(wpa_auth, neg); */
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf_len = kde.rsn_ie_len + 2 + RSN_SELECTOR_LEN + ETH_ALEN;
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf = os_malloc(buf_len);
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Initiator RSN IE */
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(buf, kde.rsn_ie, kde.rsn_ie_len);
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = buf + kde.rsn_ie_len;
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Initiator MAC Address */
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, sm->addr, ETH_ALEN,
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  NULL, 0);
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* SMK M2:
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * EAPOL-Key(S=1, M=1, A=1, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce,
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *           MIC=MIC, DataKDs=(RSNIE_I, MAC_I KDE)
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_auth_logger(wpa_auth, search.sm->addr, LOGGER_DEBUG,
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Sending SMK M2");
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	__wpa_send_eapol(wpa_auth, search.sm,
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 WPA_KEY_INFO_ACK | WPA_KEY_INFO_SMK_MESSAGE,
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 NULL, key->key_nonce, buf, pos - buf, 0, 0, 0);
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(buf);
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_send_smk_m4(struct wpa_authenticator *wpa_auth,
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    struct wpa_state_machine *sm,
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    struct wpa_eapol_key *key,
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    struct wpa_eapol_ie_parse *kde,
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    const u8 *smk)
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *buf, *pos;
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t buf_len;
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u32 lifetime;
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* SMK M4:
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * EAPOL-Key(S=1, M=1, A=0, I=1, K=0, SM=1, KeyRSC=0, Nonce=PNonce,
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *           MIC=MIC, DataKDs=(MAC_I KDE, INonce KDE, SMK KDE,
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *           Lifetime KDE)
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf_len = 2 + RSN_SELECTOR_LEN + ETH_ALEN +
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		2 + RSN_SELECTOR_LEN + WPA_NONCE_LEN +
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		2 + RSN_SELECTOR_LEN + PMK_LEN + WPA_NONCE_LEN +
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		2 + RSN_SELECTOR_LEN + sizeof(lifetime);
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = buf = os_malloc(buf_len);
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Initiator MAC Address */
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, kde->mac_addr, ETH_ALEN,
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  NULL, 0);
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Initiator Nonce */
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = wpa_add_kde(pos, RSN_KEY_DATA_NONCE, kde->nonce, WPA_NONCE_LEN,
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  NULL, 0);
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* SMK with PNonce */
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = wpa_add_kde(pos, RSN_KEY_DATA_SMK, smk, PMK_LEN,
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  key->key_nonce, WPA_NONCE_LEN);
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Lifetime */
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	lifetime = htonl(43200); /* dot11RSNAConfigSMKLifetime */
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME,
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  (u8 *) &lifetime, sizeof(lifetime), NULL, 0);
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Sending SMK M4");
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	__wpa_send_eapol(wpa_auth, sm,
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 WPA_KEY_INFO_INSTALL | WPA_KEY_INFO_SMK_MESSAGE,
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 NULL, key->key_nonce, buf, pos - buf, 0, 1, 0);
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(buf);
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_send_smk_m5(struct wpa_authenticator *wpa_auth,
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    struct wpa_state_machine *sm,
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    struct wpa_eapol_key *key,
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    struct wpa_eapol_ie_parse *kde,
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    const u8 *smk, const u8 *peer)
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *buf, *pos;
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t buf_len;
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u32 lifetime;
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* SMK M5:
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * EAPOL-Key(S=1, M=1, A=0, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce,
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *           MIC=MIC, DataKDs=(RSNIE_P, MAC_P KDE, PNonce, SMK KDE,
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *                             Lifetime KDE))
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	buf_len = kde->rsn_ie_len +
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		2 + RSN_SELECTOR_LEN + ETH_ALEN +
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		2 + RSN_SELECTOR_LEN + WPA_NONCE_LEN +
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		2 + RSN_SELECTOR_LEN + PMK_LEN + WPA_NONCE_LEN +
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		2 + RSN_SELECTOR_LEN + sizeof(lifetime);
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = buf = os_malloc(buf_len);
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Peer RSN IE */
2247d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt	os_memcpy(pos, kde->rsn_ie, kde->rsn_ie_len);
2257d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt	pos += kde->rsn_ie_len;
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Peer MAC Address */
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN, NULL, 0);
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* PNonce */
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = wpa_add_kde(pos, RSN_KEY_DATA_NONCE, key->key_nonce,
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  WPA_NONCE_LEN, NULL, 0);
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* SMK and INonce */
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = wpa_add_kde(pos, RSN_KEY_DATA_SMK, smk, PMK_LEN,
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  kde->nonce, WPA_NONCE_LEN);
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Lifetime */
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	lifetime = htonl(43200); /* dot11RSNAConfigSMKLifetime */
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME,
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  (u8 *) &lifetime, sizeof(lifetime), NULL, 0);
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Sending SMK M5");
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	__wpa_send_eapol(wpa_auth, sm,
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 WPA_KEY_INFO_SMK_MESSAGE,
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 NULL, kde->nonce, buf, pos - buf, 0, 1, 0);
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(buf);
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_smk_m3(struct wpa_authenticator *wpa_auth,
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct wpa_state_machine *sm, struct wpa_eapol_key *key)
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_eapol_ie_parse kde;
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_stsl_search search;
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 smk[32], buf[ETH_ALEN + 8 + 2 * WPA_NONCE_LEN], *pos;
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_parse_kde_ies((const u8 *) (key + 1),
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      WPA_GET_BE16(key->key_data_length), &kde) < 0) {
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M3");
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (kde.rsn_ie == NULL ||
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    kde.mac_addr == NULL || kde.mac_addr_len < ETH_ALEN ||
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    kde.nonce == NULL || kde.nonce_len < WPA_NONCE_LEN) {
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "RSN: No RSN IE, MAC address KDE, or "
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "Nonce KDE in SMK M3");
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Peer = sm->addr; Initiator = kde.mac_addr;
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Peer Nonce = key->key_nonce; Initiator Nonce = kde.nonce */
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	search.addr = kde.mac_addr;
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	search.sm = NULL;
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_auth_for_each_sta(wpa_auth, wpa_stsl_select_sta, &search) ==
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    0 || search.sm == NULL) {
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "RSN: SMK handshake with " MACSTR
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   " aborted - STA not associated anymore",
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   MAC2STR(kde.mac_addr));
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_smk_send_error(wpa_auth, sm, kde.mac_addr, STK_MUI_SMK,
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   STK_ERR_STA_NR);
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* FIX: wpa_stsl_remove(wpa_auth, neg); */
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (random_get_bytes(smk, PMK_LEN)) {
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "RSN: Failed to generate SMK");
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* SMK = PRF-256(Random number, "SMK Derivation",
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *               AA || Time || INonce || PNonce)
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(buf, wpa_auth->addr, ETH_ALEN);
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = buf + ETH_ALEN;
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_get_ntp_timestamp(pos);
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += 8;
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(pos, kde.nonce, WPA_NONCE_LEN);
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos += WPA_NONCE_LEN;
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(pos, key->key_nonce, WPA_NONCE_LEN);
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sha256_prf(smk, PMK_LEN, "SMK Derivation", buf, sizeof(buf),
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   smk, PMK_LEN);
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_IEEE80211W */
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sha1_prf(smk, PMK_LEN, "SMK Derivation", buf, sizeof(buf),
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 smk, PMK_LEN);
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_key(MSG_DEBUG, "RSN: SMK", smk, PMK_LEN);
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_send_smk_m4(wpa_auth, sm, key, &kde, smk);
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_send_smk_m5(wpa_auth, search.sm, key, &kde, smk, sm->addr);
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Authenticator does not need SMK anymore and it is required to forget
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * it. */
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(smk, 0, sizeof(*smk));
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_smk_error(struct wpa_authenticator *wpa_auth,
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   struct wpa_state_machine *sm, struct wpa_eapol_key *key)
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_eapol_ie_parse kde;
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_stsl_search search;
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct rsn_error_kde error;
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u16 mui, error_type;
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_parse_kde_ies((const u8 *) (key + 1),
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      WPA_GET_BE16(key->key_data_length), &kde) < 0) {
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK Error");
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (kde.mac_addr == NULL || kde.mac_addr_len < ETH_ALEN ||
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    kde.error == NULL || kde.error_len < sizeof(error)) {
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "RSN: No MAC address or Error KDE in "
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "SMK Error");
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	search.addr = kde.mac_addr;
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	search.sm = NULL;
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_auth_for_each_sta(wpa_auth, wpa_stsl_select_sta, &search) ==
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    0 || search.sm == NULL) {
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "RSN: Peer STA " MACSTR " not "
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "associated for SMK Error message from " MACSTR,
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   MAC2STR(kde.mac_addr), MAC2STR(sm->addr));
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(&error, kde.error, sizeof(error));
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	mui = be_to_host16(error.mui);
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	error_type = be_to_host16(error.error_type);
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 "STA reported SMK Error: Peer " MACSTR
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 " MUI %d Error Type %d",
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 MAC2STR(kde.mac_addr), mui, error_type);
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_smk_send_error(wpa_auth, search.sm, sm->addr, mui, error_type);
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_stsl_remove(struct wpa_authenticator *wpa_auth,
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    struct wpa_stsl_negotiation *neg)
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_stsl_negotiation *pos, *prev;
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_auth == NULL)
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = wpa_auth->stsl_negotiations;
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	prev = NULL;
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (pos) {
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos == neg) {
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (prev)
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				prev->next = pos->next;
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			else
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_auth->stsl_negotiations = pos->next;
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eloop_cancel_timeout(wpa_stsl_step, wpa_auth, pos);
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(pos);
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 0;
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		prev = pos;
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = pos->next;
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return -1;
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_PEERKEY */
397