15a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/*
25a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * IEEE 802.1X-2010 Key Agree Protocol of PAE state machine
35a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * Copyright (c) 2013, Qualcomm Atheros, Inc.
45a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt *
55a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * This software may be distributed under the terms of the BSD license.
65a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * See README for more details.
75a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
85a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
95a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#include <time.h>
105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#include "includes.h"
115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#include "common.h"
125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#include "list.h"
135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#include "eloop.h"
145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#include "wpabuf.h"
155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#include "state_machine.h"
165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#include "l2_packet/l2_packet.h"
175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#include "common/eapol_common.h"
185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#include "crypto/aes_wrap.h"
195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#include "ieee802_1x_cp.h"
205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#include "ieee802_1x_key.h"
215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#include "ieee802_1x_kay.h"
225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#include "ieee802_1x_kay_i.h"
235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#include "ieee802_1x_secy_ops.h"
245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#define DEFAULT_SA_KEY_LEN	16
275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#define DEFAULT_ICV_LEN		16
285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#define MAX_ICV_LEN		32  /* 32 bytes, 256 bits */
295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#define PENDING_PN_EXHAUSTION 0xC0000000
315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/* IEEE Std 802.1X-2010, Table 9-1 - MKA Algorithm Agility */
335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#define MKA_ALGO_AGILITY_2009 { 0x00, 0x80, 0xC2, 0x01 }
345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic u8 mka_algo_agility[4] = MKA_ALGO_AGILITY_2009;
355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/* IEEE802.1AE-2006 Table 14-1 MACsec Cipher Suites */
375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic struct macsec_ciphersuite cipher_suite_tbl[] = {
385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* GCM-AES-128 */
395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	{
405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		CS_ID_GCM_AES_128,
415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		CS_NAME_GCM_AES_128,
425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		MACSEC_CAP_INTEG_AND_CONF_0_30_50,
435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		16,
445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		0 /* index */
465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	},
475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt};
485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#define CS_TABLE_SIZE (ARRAY_SIZE(cipher_suite_tbl))
495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#define DEFAULT_CS_INDEX  0
505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic struct mka_alg mka_alg_tbl[] = {
525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	{
535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		MKA_ALGO_AGILITY_2009,
545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		/* 128-bit CAK, KEK, ICK, ICV */
555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		16, 16,	16, 16,
565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_cak_128bits_aes_cmac,
575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_ckn_128bits_aes_cmac,
585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_kek_128bits_aes_cmac,
595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_ick_128bits_aes_cmac,
605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_icv_128bits_aes_cmac,
615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		1, /* index */
635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	},
645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt};
655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt#define MKA_ALG_TABLE_SIZE (ARRAY_SIZE(mka_alg_tbl))
665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int is_ki_equal(struct ieee802_1x_mka_ki *ki1,
695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		       struct ieee802_1x_mka_ki *ki2)
705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return os_memcmp(ki1->mi, ki2->mi, MI_LEN) == 0 &&
725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ki1->kn == ki2->kn;
735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstruct mka_param_body_handler {
775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	int (*body_tx)(struct ieee802_1x_mka_participant *participant,
785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		       struct wpabuf *buf);
795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	int (*body_rx)(struct ieee802_1x_mka_participant *participant,
805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		       const u8 *mka_msg, size_t msg_len);
815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	int (*body_length)(struct ieee802_1x_mka_participant *participant);
825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	Boolean (*body_present)(struct ieee802_1x_mka_participant *participant);
835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt};
845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic void set_mka_param_body_len(void *body, unsigned int len)
875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_hdr *hdr = body;
895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	hdr->length = (len >> 8) & 0x0f;
905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	hdr->length1 = len & 0xff;
915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic unsigned int get_mka_param_body_len(const void *body)
955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	const struct ieee802_1x_mka_hdr *hdr = body;
975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return (hdr->length << 8) | hdr->length1;
985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
1005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
1015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int get_mka_param_body_type(const void *body)
1025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
1035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	const struct ieee802_1x_mka_hdr *hdr = body;
1045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return hdr->type;
1055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
1065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
1075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
1085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
1095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_dump_basic_body -
1105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
1115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic void
1125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_dump_basic_body(struct ieee802_1x_mka_basic_body *body)
1135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
1145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t body_len;
1155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
1165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!body)
1175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return;
1185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
1195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body_len = get_mka_param_body_len(body);
1205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "*** MKA Basic Parameter set ***");
1215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "\tVersion.......: %d", body->version);
1225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "\tPriority......: %d", body->priority);
1235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "\tKeySvr........: %d", body->key_server);
1245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "\tMACSecDesired.: %d", body->macsec_desired);
1255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "\tMACSecCapable.: %d", body->macsec_capbility);
1265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "\tBody Length...: %d", (int) body_len);
1275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "\tSCI MAC.......: " MACSTR,
1285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		   MAC2STR(body->actor_sci.addr));
1295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "\tSCI Port .....: %d",
1305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		   be_to_host16(body->actor_sci.port));
1315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_hexdump(MSG_DEBUG, "\tMember Id.....:",
1325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		    body->actor_mi, sizeof(body->actor_mi));
1335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "\tMessage Number: %d",
1345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		   be_to_host32(body->actor_mn));
1355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_hexdump(MSG_DEBUG, "\tAlgo Agility..:",
1365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		    body->algo_agility, sizeof(body->algo_agility));
1375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_hexdump_ascii(MSG_DEBUG, "\tCAK Name......:", body->ckn,
1385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			  body_len + MKA_HDR_LEN - sizeof(*body));
1395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
1405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
1415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
1425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
1435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_dump_peer_body -
1445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
1455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic void
1465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_dump_peer_body(struct ieee802_1x_mka_peer_body *body)
1475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
1485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t body_len;
1495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t i;
1505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	u8 *mi;
1515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	u32 mn;
1525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
1535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (body == NULL)
1545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return;
1555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
1565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body_len = get_mka_param_body_len(body);
1575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (body->type == MKA_LIVE_PEER_LIST) {
1585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_DEBUG, "*** Live Peer List ***");
1595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_DEBUG, "\tBody Length...: %d", (int) body_len);
1605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	} else if (body->type == MKA_POTENTIAL_PEER_LIST) {
1615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_DEBUG, "*** Potential Live Peer List ***");
1625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_DEBUG, "\tBody Length...: %d", (int) body_len);
1635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
1645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
1655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	for (i = 0; i < body_len; i += MI_LEN + sizeof(mn)) {
1665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		mi = body->peer + i;
1675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_memcpy(&mn, mi + MI_LEN, sizeof(mn));
1685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_hexdump_ascii(MSG_DEBUG, "\tMember Id.....:", mi, MI_LEN);
1695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_DEBUG, "\tMessage Number: %d", be_to_host32(mn));
1705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
1715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
1725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
1735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
1745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
1755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_dump_dist_sak_body -
1765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
1775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic void
1785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_dump_dist_sak_body(struct ieee802_1x_mka_dist_sak_body *body)
1795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
1805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t body_len;
1815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
1825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (body == NULL)
1835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return;
1845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
1855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body_len = get_mka_param_body_len(body);
1865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_INFO, "*** Distributed SAK ***");
1875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_INFO, "\tDistributed AN........: %d", body->dan);
1885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_INFO, "\tConfidentiality Offset: %d",
1895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		   body->confid_offset);
1905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_INFO, "\tBody Length...........: %d", (int) body_len);
1915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!body_len)
1925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return;
1935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
1945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_INFO, "\tKey Number............: %d",
1955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		   be_to_host32(body->kn));
1965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_hexdump(MSG_INFO, "\tAES Key Wrap of SAK...:", body->sak, 24);
1975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
1985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
1995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
2005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic const char * yes_no(int val)
2015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
2025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return val ? "Yes" : "No";
2035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
2045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
2055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
2065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
2075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_dump_sak_use_body -
2085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
2095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic void
2105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_dump_sak_use_body(struct ieee802_1x_mka_sak_use_body *body)
2115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
2125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	int body_len;
2135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
2145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (body == NULL)
2155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return;
2165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
2175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body_len = get_mka_param_body_len(body);
2185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "*** MACsec SAK Use ***");
2195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "\tLatest Key AN....: %d", body->lan);
2205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "\tLatest Key Tx....: %s", yes_no(body->ltx));
2215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "\tLatest Key Rx....: %s", yes_no(body->lrx));
2225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "\tOld Key AN....: %d", body->oan);
2235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "\tOld Key Tx....: %s", yes_no(body->otx));
2245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "\tOld Key Rx....: %s", yes_no(body->orx));
2255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "\tPlain Key Tx....: %s", yes_no(body->ptx));
2265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "\tPlain Key Rx....: %s", yes_no(body->prx));
2275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "\tDelay Protect....: %s",
2285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		   yes_no(body->delay_protect));
2295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "\tBody Length......: %d", body_len);
2305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!body_len)
2315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return;
2325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
2335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_hexdump(MSG_DEBUG, "\tKey Server MI....:",
2345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		    body->lsrv_mi, sizeof(body->lsrv_mi));
2355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "\tKey Number.......: %u",
2365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		   be_to_host32(body->lkn));
2375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "\tLowest PN........: %u",
2385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		   be_to_host32(body->llpn));
2395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_hexdump_ascii(MSG_DEBUG, "\tOld Key Server MI....:",
2405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			  body->osrv_mi, sizeof(body->osrv_mi));
2415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "\tOld Key Number.......: %u",
2425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		   be_to_host32(body->okn));
2435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "\tOld Lowest PN........: %u",
2445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		   be_to_host32(body->olpn));
2455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
2465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
2475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
2485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
2495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_get_participant -
2505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
2515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic struct ieee802_1x_mka_participant *
2525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_get_participant(struct ieee802_1x_kay *kay, const u8 *ckn)
2535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
2545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant;
2555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
2565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(participant, &kay->participant_list,
2575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			 struct ieee802_1x_mka_participant, list) {
2585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (os_memcmp(participant->ckn.name, ckn,
2595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			      participant->ckn.len) == 0)
2605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			return participant;
2615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
2625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
2635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "KaY: participant is not found");
2645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
2655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return NULL;
2665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
2675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
2685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
2695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
2705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_get_principal_participant -
2715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
2725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic struct ieee802_1x_mka_participant *
2735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_get_principal_participant(struct ieee802_1x_kay *kay)
2745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
2755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant;
2765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
2775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(participant, &kay->participant_list,
2785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			 struct ieee802_1x_mka_participant, list) {
2795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (participant->principal)
2805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			return participant;
2815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
2825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
2835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "KaY: principal participant is not founded");
2845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return NULL;
2855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
2865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
2875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
2885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic struct ieee802_1x_kay_peer * get_peer_mi(struct dl_list *peers,
2895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt						const u8 *mi)
2905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
2915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay_peer *peer;
2925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
2935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(peer, peers, struct ieee802_1x_kay_peer, list) {
2945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (os_memcmp(peer->mi, mi, MI_LEN) == 0)
2955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			return peer;
2965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
2975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
2985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return NULL;
2995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
3005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
3015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
3025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
3035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_is_in_potential_peer
3045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
3055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic Boolean
3065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_is_in_potential_peer(
3075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant, const u8 *mi)
3085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
3095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return get_peer_mi(&participant->potential_peers, mi) != NULL;
3105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
3115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
3125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
3135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
3145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_is_in_live_peer
3155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
3165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic Boolean
3175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_is_in_live_peer(
3185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant, const u8 *mi)
3195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
3205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return get_peer_mi(&participant->live_peers, mi) != NULL;
3215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
3225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
3235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
3245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
3255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_is_in_peer
3265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
3275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic Boolean
3285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_is_in_peer(struct ieee802_1x_mka_participant *participant,
3295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			  const u8 *mi)
3305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
3315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return ieee802_1x_kay_is_in_live_peer(participant, mi) ||
3325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_kay_is_in_potential_peer(participant, mi);
3335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
3345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
3355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
3365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
3375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_get_peer
3385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
3395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic struct ieee802_1x_kay_peer *
3405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_get_peer(struct ieee802_1x_mka_participant *participant,
3415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			const u8 *mi)
3425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
3435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay_peer *peer;
3445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
3455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	peer = get_peer_mi(&participant->live_peers, mi);
3465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (peer)
3475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return peer;
3485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
3495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return get_peer_mi(&participant->potential_peers, mi);
3505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
3515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
3525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
3535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
3545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_get_live_peer
3555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
3565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic struct ieee802_1x_kay_peer *
3575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_get_live_peer(struct ieee802_1x_mka_participant *participant,
3585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			     const u8 *mi)
3595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
3605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return get_peer_mi(&participant->live_peers, mi);
3615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
3625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
3635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
3645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
3655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_get_cipher_suite
3665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
3675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic struct macsec_ciphersuite *
3685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_get_cipher_suite(struct ieee802_1x_mka_participant *participant,
3695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				u8 *cs_id)
3705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
3715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	unsigned int i;
3725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
3735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	for (i = 0; i < CS_TABLE_SIZE; i++) {
3745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (os_memcmp(cipher_suite_tbl[i].id, cs_id, CS_ID_LEN) == 0)
3755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			break;
3765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
3775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (i >= CS_TABLE_SIZE)
3785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return NULL;
3795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
3805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return &cipher_suite_tbl[i];
3815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
3825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
3835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
3845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
3855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_get_peer_sci
3865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
3875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic struct ieee802_1x_kay_peer *
3885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_get_peer_sci(struct ieee802_1x_mka_participant *participant,
3895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			    const struct ieee802_1x_mka_sci *sci)
3905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
3915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay_peer *peer;
3925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
3935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(peer, &participant->live_peers,
3945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			 struct ieee802_1x_kay_peer, list) {
3955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (os_memcmp(&peer->sci, sci, sizeof(peer->sci)) == 0)
3965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			return peer;
3975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
3985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
3995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(peer, &participant->potential_peers,
4005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			 struct ieee802_1x_kay_peer, list) {
4015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (os_memcmp(&peer->sci, sci, sizeof(peer->sci)) == 0)
4025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			return peer;
4035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
4045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
4055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return NULL;
4065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
4075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
4085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
4095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
4105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_init_receive_sa -
4115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
4125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic struct receive_sa *
4135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_init_receive_sa(struct receive_sc *psc, u8 an, u32 lowest_pn,
4145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			       struct data_key *key)
4155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
4165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct receive_sa *psa;
4175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
4185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!psc || !key)
4195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return NULL;
4205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
4215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	psa = os_zalloc(sizeof(*psa));
4225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!psa) {
4235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "%s: out of memory", __func__);
4245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return NULL;
4255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
4265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
4275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	psa->pkey = key;
4285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	psa->lowest_pn = lowest_pn;
4295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	psa->next_pn = lowest_pn;
4305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	psa->an = an;
4315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	psa->sc = psc;
4325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
4335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_get_time(&psa->created_time);
4345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	psa->in_use = FALSE;
4355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
4365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_add(&psc->sa_list, &psa->list);
4375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG,
4385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		   "KaY: Create receive SA(AN: %d lowest_pn: %u of SC(channel: %d)",
4395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		   (int) an, lowest_pn, psc->channel);
4405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
4415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return psa;
4425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
4435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
4445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
4455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
4465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_deinit_receive_sa -
4475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
4485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic void ieee802_1x_kay_deinit_receive_sa(struct receive_sa *psa)
4495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
4505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	psa->pkey = NULL;
4515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG,
4525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		   "KaY: Delete receive SA(an: %d) of SC(channel: %d)",
4535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		   psa->an, psa->sc->channel);
4545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_del(&psa->list);
4555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_free(psa);
4565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
4575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
4585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
4595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
4605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_init_receive_sc -
4615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
4625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic struct receive_sc *
4635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_init_receive_sc(const struct ieee802_1x_mka_sci *psci,
4645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			       int channel)
4655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
4665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct receive_sc *psc;
4675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
4685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!psci)
4695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return NULL;
4705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
4715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	psc = os_zalloc(sizeof(*psc));
4725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!psc) {
4735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "%s: out of memory", __func__);
4745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return NULL;
4755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
4765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
4775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(&psc->sci, psci, sizeof(psc->sci));
4785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	psc->channel = channel;
4795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
4805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_get_time(&psc->created_time);
4815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	psc->receiving = FALSE;
4825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
4835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_init(&psc->sa_list);
4845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "KaY: Create receive SC(channel: %d)", channel);
4855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_hexdump(MSG_DEBUG, "SCI: ", (u8 *)psci, sizeof(*psci));
4865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
4875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return psc;
4885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
4895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
4905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
4915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
4925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_deinit_receive_sc -
4935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt **/
4945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic void
4955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_deinit_receive_sc(
4965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant, struct receive_sc *psc)
4975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
4985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct receive_sa *psa, *pre_sa;
4995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
5005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "KaY: Delete receive SC(channel: %d)",
5015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		   psc->channel);
5025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each_safe(psa, pre_sa, &psc->sa_list, struct receive_sa,
5035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			      list)  {
5045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		secy_disable_receive_sa(participant->kay, psa);
5055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_kay_deinit_receive_sa(psa);
5065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
5075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_del(&psc->list);
5085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_free(psc);
5095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
5105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
5115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
5125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
5135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_create_live_peer
5145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
5155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic struct ieee802_1x_kay_peer *
5165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_create_live_peer(struct ieee802_1x_mka_participant *participant,
5175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				u8 *mi, u32 mn)
5185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
5195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay_peer *peer;
5205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct receive_sc *rxsc;
5215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	u32 sc_ch = 0;
5225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
5235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	peer = os_zalloc(sizeof(*peer));
5245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (peer == NULL) {
5255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY-%s: out of memory", __func__);
5265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return NULL;
5275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
5285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
5295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(peer->mi, mi, MI_LEN);
5305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	peer->mn = mn;
5315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	peer->expire = time(NULL) + MKA_LIFE_TIME / 1000;
5325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	peer->sak_used = FALSE;
5335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(&peer->sci, &participant->current_peer_sci,
5345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		  sizeof(peer->sci));
5355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_add(&participant->live_peers, &peer->list);
5365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
5375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	secy_get_available_receive_sc(participant->kay, &sc_ch);
5385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
5395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	rxsc = ieee802_1x_kay_init_receive_sc(&peer->sci, sc_ch);
5405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!rxsc)
5415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return NULL;
5425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
5435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_add(&participant->rxsc_list, &rxsc->list);
5445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	secy_create_receive_sc(participant->kay, rxsc);
5455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
5465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "KaY: Live peer created");
5475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_hexdump(MSG_DEBUG, "\tMI: ", peer->mi, sizeof(peer->mi));
5485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "\tMN: %d", peer->mn);
5495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_hexdump(MSG_DEBUG, "\tSCI Addr: ", peer->sci.addr, ETH_ALEN);
5505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "\tPort: %d", peer->sci.port);
5515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
5525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return peer;
5535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
5545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
5555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
5565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
5575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_create_potential_peer
5585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
5595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic struct ieee802_1x_kay_peer *
5605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_create_potential_peer(
5615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant, const u8 *mi, u32 mn)
5625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
5635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay_peer *peer;
5645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
5655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	peer = os_zalloc(sizeof(*peer));
5665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (peer == NULL) {
5675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY-%s: out of memory", __func__);
5685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return NULL;
5695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
5705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
5715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(peer->mi, mi, MI_LEN);
5725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	peer->mn = mn;
5735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	peer->expire = time(NULL) + MKA_LIFE_TIME / 1000;
5745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	peer->sak_used = FALSE;
5755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
5765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_add(&participant->potential_peers, &peer->list);
5775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
5785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "KaY: potential peer created");
5795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_hexdump(MSG_DEBUG, "\tMI: ", peer->mi, sizeof(peer->mi));
5805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "\tMN: %d", peer->mn);
5815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_hexdump(MSG_DEBUG, "\tSCI Addr: ", peer->sci.addr, ETH_ALEN);
5825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "\tPort: %d", peer->sci.port);
5835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
5845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return peer;
5855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
5865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
5875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
5885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
5895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_move_live_peer
5905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
5915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic struct ieee802_1x_kay_peer *
5925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_move_live_peer(struct ieee802_1x_mka_participant *participant,
5935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			      u8 *mi, u32 mn)
5945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
5955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay_peer *peer;
5965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct receive_sc *rxsc;
5975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	u32 sc_ch = 0;
5985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
5995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(peer, &participant->potential_peers,
6005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			 struct ieee802_1x_kay_peer, list) {
6015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (os_memcmp(peer->mi, mi, MI_LEN) == 0)
6025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			break;
6035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
6045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
6055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(&peer->sci, &participant->current_peer_sci,
6065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		  sizeof(peer->sci));
6075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	peer->mn = mn;
6085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	peer->expire = time(NULL) + MKA_LIFE_TIME / 1000;
6095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
6105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "KaY: move potential peer to live peer");
6115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_hexdump(MSG_DEBUG, "\tMI: ", peer->mi, sizeof(peer->mi));
6125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "\tMN: %d", peer->mn);
6135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_hexdump(MSG_DEBUG, "\tSCI Addr: ", peer->sci.addr, ETH_ALEN);
6145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "\tPort: %d", peer->sci.port);
6155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
6165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_del(&peer->list);
6175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_add_tail(&participant->live_peers, &peer->list);
6185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
6195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	secy_get_available_receive_sc(participant->kay, &sc_ch);
6205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
6215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	rxsc = ieee802_1x_kay_init_receive_sc(&peer->sci, sc_ch);
6225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!rxsc)
6235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return NULL;
6245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
6255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_add(&participant->rxsc_list, &rxsc->list);
6265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	secy_create_receive_sc(participant->kay, rxsc);
6275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
6285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return peer;
6295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
6305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
6315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
6325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
6335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
6345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt *  ieee802_1x_mka_basic_body_present -
6355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
6365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic Boolean
6375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_basic_body_present(
6385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant)
6395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
6405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return TRUE;
6415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
6425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
6435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
6445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
6455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_basic_body_length -
6465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
6475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
6485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_basic_body_length(struct ieee802_1x_mka_participant *participant)
6495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
6505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	int length;
6515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
6525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	length = sizeof(struct ieee802_1x_mka_basic_body);
6535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	length += participant->ckn.len;
6545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return (length + 0x3) & ~0x3;
6555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
6565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
6575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
6585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
6595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_encode_basic_body
6605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
6615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
6625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_encode_basic_body(
6635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant,
6645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct wpabuf *buf)
6655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
6665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_basic_body *body;
6675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay *kay = participant->kay;
6685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	unsigned int length = ieee802_1x_mka_basic_body_length(participant);
6695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
6705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body = wpabuf_put(buf, length);
6715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
6725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body->version = kay->mka_version;
6735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body->priority = kay->actor_priority;
6745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (participant->is_elected)
6755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body->key_server = participant->is_key_server;
6765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	else
6775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body->key_server = participant->can_be_key_server;
6785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
6795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body->macsec_desired = kay->macsec_desired;
6805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body->macsec_capbility = kay->macsec_capable;
6815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	set_mka_param_body_len(body, length - MKA_HDR_LEN);
6825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
6835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(body->actor_sci.addr, kay->actor_sci.addr,
6845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		  sizeof(kay->actor_sci.addr));
6855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body->actor_sci.port = host_to_be16(kay->actor_sci.port);
6865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
6875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(body->actor_mi, participant->mi, sizeof(body->actor_mi));
6885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->mn = participant->mn + 1;
6895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body->actor_mn = host_to_be32(participant->mn);
6905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(body->algo_agility, participant->kay->algo_agility,
6915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		  sizeof(body->algo_agility));
6925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
6935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(body->ckn, participant->ckn.name, participant->ckn.len);
6945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
6955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_mka_dump_basic_body(body);
6965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
6975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
6985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
6995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
7005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
7015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
7025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_decode_basic_body -
7035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
7045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic struct ieee802_1x_mka_participant *
7055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_decode_basic_body(struct ieee802_1x_kay *kay, const u8 *mka_msg,
7065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				 size_t msg_len)
7075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
7085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant;
7095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	const struct ieee802_1x_mka_basic_body *body;
7105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay_peer *peer;
7115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
7125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body = (const struct ieee802_1x_mka_basic_body *) mka_msg;
7135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
7145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (body->version > MKA_VERSION_ID) {
7155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_DEBUG,
7165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   "KaY: peer's version(%d) greater than mka current version(%d)",
7175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   body->version, MKA_VERSION_ID);
7185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
7195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (kay->is_obliged_key_server && body->key_server) {
7205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_DEBUG, "I must be as key server");
7215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return NULL;
7225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
7235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
7245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant = ieee802_1x_kay_get_participant(kay, body->ckn);
7255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!participant) {
7265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_DEBUG, "Peer is not included in my CA");
7275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return NULL;
7285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
7295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
7305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* If the peer's MI is my MI, I will choose new MI */
7315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (os_memcmp(body->actor_mi, participant->mi, MI_LEN) == 0) {
7325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_get_random(participant->mi, sizeof(participant->mi));
7335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->mn = 0;
7345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
7355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
7365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(participant->current_peer_id.mi, body->actor_mi, MI_LEN);
7375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->current_peer_id.mn =  be_to_host32(body->actor_mn);
7385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(participant->current_peer_sci.addr, body->actor_sci.addr,
7395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		  sizeof(participant->current_peer_sci.addr));
7405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->current_peer_sci.port = be_to_host16(body->actor_sci.port);
7415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
7425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* handler peer */
7435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	peer = ieee802_1x_kay_get_peer(participant, body->actor_mi);
7445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!peer) {
7455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		/* Check duplicated SCI */
7465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		/* TODO: What policy should be applied to detect duplicated SCI
7475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		 * is active attacker or a valid peer whose MI is be changed?
7485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		 */
7495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		peer = ieee802_1x_kay_get_peer_sci(participant,
7505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt						   &body->actor_sci);
7515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (peer) {
7525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			wpa_printf(MSG_WARNING,
7535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				   "KaY: duplicated SCI detected, Maybe active attacker");
7545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			dl_list_del(&peer->list);
7555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			os_free(peer);
7565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
7575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
7585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		peer = ieee802_1x_kay_create_potential_peer(
7595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant, body->actor_mi,
7605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			be_to_host32(body->actor_mn));
7615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (!peer)
7625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			return NULL;
7635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
7645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		peer->macsec_desired = body->macsec_desired;
7655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		peer->macsec_capbility = body->macsec_capbility;
7665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		peer->is_key_server = (Boolean) body->key_server;
7675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		peer->key_server_priority = body->priority;
7685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	} else if (peer->mn < be_to_host32(body->actor_mn)) {
7695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		peer->mn = be_to_host32(body->actor_mn);
7705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		peer->expire = time(NULL) + MKA_LIFE_TIME / 1000;
7715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		peer->macsec_desired = body->macsec_desired;
7725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		peer->macsec_capbility = body->macsec_capbility;
7735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		peer->is_key_server = (Boolean) body->key_server;
7745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		peer->key_server_priority = body->priority;
7755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	} else {
7765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_WARNING, "KaY: The peer MN have received");
7775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return NULL;
7785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
7795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
7805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return participant;
7815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
7825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
7835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
7845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
7855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_live_peer_body_present
7865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
7875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic Boolean
7885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_live_peer_body_present(
7895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant)
7905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
7915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return !dl_list_empty(&participant->live_peers);
7925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
7935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
7945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
7955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
7965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_get_live_peer_length
7975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
7985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
7995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_get_live_peer_length(
8005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant)
8015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
8025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	int len = MKA_HDR_LEN;
8035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay_peer *peer;
8045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
8055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(peer, &participant->live_peers,
8065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			 struct ieee802_1x_kay_peer, list)
8075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		len += sizeof(struct ieee802_1x_mka_peer_id);
8085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
8095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return (len + 0x3) & ~0x3;
8105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
8115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
8125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
8135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
8145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_encode_live_peer_body -
8155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
8165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
8175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_encode_live_peer_body(
8185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant,
8195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct wpabuf *buf)
8205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
8215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_peer_body *body;
8225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay_peer *peer;
8235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	unsigned int length;
8245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_peer_id *body_peer;
8255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
8265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	length = ieee802_1x_mka_get_live_peer_length(participant);
8275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body = wpabuf_put(buf, sizeof(struct ieee802_1x_mka_peer_body));
8285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
8295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body->type = MKA_LIVE_PEER_LIST;
8305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	set_mka_param_body_len(body, length - MKA_HDR_LEN);
8315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
8325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(peer, &participant->live_peers,
8335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			 struct ieee802_1x_kay_peer, list) {
8345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body_peer = wpabuf_put(buf,
8355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				       sizeof(struct ieee802_1x_mka_peer_id));
8365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_memcpy(body_peer->mi, peer->mi, MI_LEN);
8375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body_peer->mn = host_to_be32(peer->mn);
8385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body_peer++;
8395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
8405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
8415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_mka_dump_peer_body(body);
8425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
8435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
8445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
8455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
8465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_potential_peer_body_present
8475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
8485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic Boolean
8495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_potential_peer_body_present(
8505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant)
8515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
8525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return !dl_list_empty(&participant->potential_peers);
8535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
8545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
8555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
8565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
8575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_get_potential_peer_length
8585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
8595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
8605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_get_potential_peer_length(
8615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant)
8625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
8635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	int len = MKA_HDR_LEN;
8645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay_peer *peer;
8655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
8665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(peer, &participant->potential_peers,
8675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			 struct ieee802_1x_kay_peer, list)
8685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		len += sizeof(struct ieee802_1x_mka_peer_id);
8695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
8705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return (len + 0x3) & ~0x3;
8715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
8725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
8735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
8745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
8755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_encode_potential_peer_body -
8765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
8775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
8785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_encode_potential_peer_body(
8795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant,
8805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct wpabuf *buf)
8815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
8825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_peer_body *body;
8835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay_peer *peer;
8845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	unsigned int length;
8855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_peer_id *body_peer;
8865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
8875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	length = ieee802_1x_mka_get_potential_peer_length(participant);
8885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body = wpabuf_put(buf, sizeof(struct ieee802_1x_mka_peer_body));
8895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
8905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body->type = MKA_POTENTIAL_PEER_LIST;
8915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	set_mka_param_body_len(body, length - MKA_HDR_LEN);
8925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
8935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(peer, &participant->potential_peers,
8945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			 struct ieee802_1x_kay_peer, list) {
8955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body_peer = wpabuf_put(buf,
8965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				       sizeof(struct ieee802_1x_mka_peer_id));
8975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_memcpy(body_peer->mi, peer->mi, MI_LEN);
8985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body_peer->mn = host_to_be32(peer->mn);
8995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body_peer++;
9005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
9015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
9025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_mka_dump_peer_body(body);
9035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
9045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
9055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
9065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
9075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
9085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_i_in_peerlist -
9095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
9105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic Boolean
9115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_i_in_peerlist(struct ieee802_1x_mka_participant *participant,
9125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			     const u8 *mka_msg, size_t msg_len)
9135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
9145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	Boolean included = FALSE;
9155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_hdr *hdr;
9165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t body_len;
9175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t left_len;
9185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	int body_type;
9195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	u32 peer_mn;
9205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	const u8 *peer_mi;
9215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	const u8 *pos;
9225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t i;
9235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
9245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	pos = mka_msg;
9255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	left_len = msg_len;
9265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	while (left_len > (MKA_HDR_LEN + DEFAULT_ICV_LEN)) {
9275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		hdr = (struct ieee802_1x_mka_hdr *) pos;
9285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body_len = get_mka_param_body_len(hdr);
9295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body_type = get_mka_param_body_type(hdr);
9305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
9315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (body_type != MKA_LIVE_PEER_LIST &&
9325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		    body_type != MKA_POTENTIAL_PEER_LIST)
9335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			goto SKIP_PEER;
9345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
9355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_dump_peer_body(
9365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			(struct ieee802_1x_mka_peer_body *)pos);
9375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
9385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (left_len < (MKA_HDR_LEN + body_len + DEFAULT_ICV_LEN)) {
9395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			wpa_printf(MSG_ERROR,
9405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				   "KaY: MKA Peer Packet Body Length (%d bytes) is less than the Parameter Set Header Length (%d bytes) + the Parameter Set Body Length (%d bytes) + %d bytes of ICV",
9415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				   (int) left_len, (int) MKA_HDR_LEN,
9425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				   (int) body_len, DEFAULT_ICV_LEN);
9435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			goto SKIP_PEER;
9445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
9455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
9465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if ((body_len % 16) != 0) {
9475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			wpa_printf(MSG_ERROR,
9485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				   "KaY: MKA Peer Packet Body Length (%d bytes) should multiple of 16 octets",
9495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				   (int) body_len);
9505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			goto SKIP_PEER;
9515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
9525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
9535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		for (i = 0; i < body_len; i += MI_LEN + sizeof(peer_mn)) {
9545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			peer_mi = MKA_HDR_LEN + pos + i;
9555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			os_memcpy(&peer_mn, peer_mi + MI_LEN, sizeof(peer_mn));
9565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			peer_mn = be_to_host32(peer_mn);
9575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			if (os_memcmp(peer_mi, participant->mi, MI_LEN) == 0 &&
9585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			    peer_mn == participant->mn) {
9595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				included = TRUE;
9605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				break;
9615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			}
9625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
9635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
9645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (included)
9655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			return TRUE;
9665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
9675a1480c7c46c4236d93bfd303dde32062bee04acDmitry ShmidtSKIP_PEER:
9685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		left_len -= body_len + MKA_HDR_LEN;
9695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		pos += body_len + MKA_HDR_LEN;
9705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
9715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
9725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return FALSE;
9735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
9745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
9755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
9765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
9775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_decode_live_peer_body -
9785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
9795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int ieee802_1x_mka_decode_live_peer_body(
9805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant,
9815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	const u8 *peer_msg, size_t msg_len)
9825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
9835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	const struct ieee802_1x_mka_hdr *hdr;
9845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay_peer *peer;
9855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t body_len;
9865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	u32 peer_mn;
9875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	const u8 *peer_mi;
9885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t i;
9895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	Boolean is_included;
9905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
9915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	is_included = ieee802_1x_kay_is_in_live_peer(
9925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant, participant->current_peer_id.mi);
9935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
9945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	hdr = (const struct ieee802_1x_mka_hdr *) peer_msg;
9955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body_len = get_mka_param_body_len(hdr);
9965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
9975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	for (i = 0; i < body_len; i += MI_LEN + sizeof(peer_mn)) {
9985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		peer_mi = MKA_HDR_LEN + peer_msg + i;
9995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_memcpy(&peer_mn, peer_mi + MI_LEN, sizeof(peer_mn));
10005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		peer_mn = be_to_host32(peer_mn);
10015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
10025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		/* it is myself */
10035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (os_memcmp(peer_mi, participant->mi, MI_LEN) == 0) {
10045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			/* My message id is used by other participant */
10055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			if (peer_mn > participant->mn) {
10065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				os_get_random(participant->mi,
10075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					      sizeof(participant->mi));
10085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				participant->mn = 0;
10095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			}
10105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			continue;
10115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
10125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (!is_included)
10135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			continue;
10145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
10155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		peer = ieee802_1x_kay_get_peer(participant, peer_mi);
10165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (NULL != peer) {
10175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			peer->mn = peer_mn;
10185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			peer->expire = time(NULL) + MKA_LIFE_TIME / 1000;
10195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		} else {
10205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			if (!ieee802_1x_kay_create_potential_peer(
10215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				participant, peer_mi, peer_mn)) {
10225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				return -1;
10235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			}
10245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
10255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
10265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
10275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
10285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
10295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
10305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
10315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
10325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_decode_potential_peer_body -
10335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
10345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
10355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_decode_potential_peer_body(
10365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant,
10375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	const u8 *peer_msg, size_t msg_len)
10385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
10395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_hdr *hdr;
10405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t body_len;
10415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	u32 peer_mn;
10425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	const u8 *peer_mi;
10435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t i;
10445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
10455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	hdr = (struct ieee802_1x_mka_hdr *) peer_msg;
10465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body_len = get_mka_param_body_len(hdr);
10475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
10485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	for (i = 0; i < body_len; i += MI_LEN + sizeof(peer_mn)) {
10495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		peer_mi = MKA_HDR_LEN + peer_msg + i;
10505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_memcpy(&peer_mn, peer_mi + MI_LEN, sizeof(peer_mn));
10515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		peer_mn = be_to_host32(peer_mn);
10525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
10535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		/* it is myself */
10545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (os_memcmp(peer_mi, participant->mi, MI_LEN) == 0) {
10555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			/* My message id is used by other participant */
10565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			if (peer_mn > participant->mn) {
10575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				os_get_random(participant->mi,
10585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					      sizeof(participant->mi));
10595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				participant->mn = 0;
10605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			}
10615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			continue;
10625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
10635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
10645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
10655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
10665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
10675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
10685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
10695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
10705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_sak_use_body_present
10715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
10725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic Boolean
10735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_sak_use_body_present(
10745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant)
10755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
10765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (participant->to_use_sak)
10775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return TRUE;
10785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	else
10795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return FALSE;
10805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
10815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
10825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
10835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
10845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_get_sak_use_length
10855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
10865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
10875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_get_sak_use_length(
10885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant)
10895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
10905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	int length = MKA_HDR_LEN;
10915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
10925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (participant->kay->macsec_desired && participant->advised_desired)
10935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		length = sizeof(struct ieee802_1x_mka_sak_use_body);
10945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	else
10955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		length = MKA_HDR_LEN;
10965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
10975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	length = (length + 0x3) & ~0x3;
10985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
10995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return length;
11005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
11015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
11025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
11035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
11045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt *
11055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
11065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic u32
11075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_get_lpn(struct ieee802_1x_mka_participant *principal,
11085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		       struct ieee802_1x_mka_ki *ki)
11095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
11105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct receive_sa *rxsa;
11115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct receive_sc *rxsc;
11125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	u32 lpn = 0;
11135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
11145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(rxsc, &principal->rxsc_list, struct receive_sc, list) {
11155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		dl_list_for_each(rxsa, &rxsc->sa_list, struct receive_sa, list)
11165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		{
11175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			if (is_ki_equal(&rxsa->pkey->key_identifier, ki)) {
11185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				secy_get_receive_lowest_pn(principal->kay,
11195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt							   rxsa);
11205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
11215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				lpn = lpn > rxsa->lowest_pn ?
11225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					lpn : rxsa->lowest_pn;
11235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				break;
11245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			}
11255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
11265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
11275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
11285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (lpn == 0)
11295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		lpn = 1;
11305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
11315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return lpn;
11325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
11335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
11345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
11355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
11365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_encode_sak_use_body -
11375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
11385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
11395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_encode_sak_use_body(
11405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant,
11415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct wpabuf *buf)
11425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
11435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_sak_use_body *body;
11445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	unsigned int length;
11455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	u32 pn = 1;
11465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
11475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	length = ieee802_1x_mka_get_sak_use_length(participant);
11485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body = wpabuf_put(buf, sizeof(struct ieee802_1x_mka_sak_use_body));
11495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
11505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body->type = MKA_SAK_USE;
11515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	set_mka_param_body_len(body, length - MKA_HDR_LEN);
11525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
11535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (length == MKA_HDR_LEN) {
11545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body->ptx = TRUE;
11555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body->prx = TRUE;
11565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body->lan = 0;
11575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body->lrx = FALSE;
11585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body->ltx = FALSE;
11595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body->delay_protect = FALSE;
11605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return 0;
11615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
11625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
11635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* data protect, lowest accept packet number */
11645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body->delay_protect = participant->kay->macsec_replay_protect;
11655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	pn = ieee802_1x_mka_get_lpn(participant, &participant->lki);
11665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (pn > participant->kay->pn_exhaustion) {
11675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_WARNING, "KaY: My LPN exhaustion");
11685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (participant->is_key_server)
11695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->new_sak = TRUE;
11705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
11715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
11725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body->llpn = host_to_be32(pn);
11735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	pn = ieee802_1x_mka_get_lpn(participant, &participant->oki);
11745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body->olpn = host_to_be32(pn);
11755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
11765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* plain tx, plain rx */
11775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (participant->kay->macsec_protect)
11785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body->ptx = FALSE;
11795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	else
11805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body->ptx = TRUE;
11815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
11825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (participant->kay->macsec_validate == Strict)
11835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body->prx = FALSE;
11845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	else
11855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body->prx = TRUE;
11865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
11875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* latest key: rx, tx, key server member identifier key number */
11885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body->lan = participant->lan;
11895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(body->lsrv_mi, participant->lki.mi,
11905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		  sizeof(body->lsrv_mi));
11915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body->lkn = host_to_be32(participant->lki.kn);
11925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body->lrx = participant->lrx;
11935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body->ltx = participant->ltx;
11945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
11955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* old key: rx, tx, key server member identifier key number */
11965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body->oan = participant->oan;
11975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (participant->oki.kn != participant->lki.kn &&
11985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	    participant->oki.kn != 0) {
11995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body->otx = TRUE;
12005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body->orx = TRUE;
12015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_memcpy(body->osrv_mi, participant->oki.mi,
12025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			  sizeof(body->osrv_mi));
12035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body->okn = host_to_be32(participant->oki.kn);
12045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	} else {
12055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body->otx = FALSE;
12065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body->orx = FALSE;
12075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
12085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
12095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* set CP's variable */
12105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (body->ltx) {
12115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (!participant->kay->tx_enable)
12125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->kay->tx_enable = TRUE;
12135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
12145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (!participant->kay->port_enable)
12155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->kay->port_enable = TRUE;
12165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
12175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (body->lrx) {
12185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (!participant->kay->rx_enable)
12195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->kay->rx_enable = TRUE;
12205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
12215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
12225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_mka_dump_sak_use_body(body);
12235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
12245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
12255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
12265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
12275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
12285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_decode_sak_use_body -
12295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
12305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
12315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_decode_sak_use_body(
12325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant,
12335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	const u8 *mka_msg, size_t msg_len)
12345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
12355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_hdr *hdr;
12365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_sak_use_body *body;
12375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay_peer *peer;
12385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct transmit_sa *txsa;
12395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct data_key *sa_key = NULL;
12405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t body_len;
12415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_ki ki;
12425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	u32 lpn;
12435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	Boolean all_receiving;
12445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	Boolean founded;
12455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
12465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!participant->principal) {
12475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_WARNING, "KaY: Participant is not principal");
12485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
12495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
12505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	peer = ieee802_1x_kay_get_live_peer(participant,
12515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					    participant->current_peer_id.mi);
12525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!peer) {
12535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_WARNING, "KaY: the peer is not my live peer");
12545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
12555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
12565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
12575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	hdr = (struct ieee802_1x_mka_hdr *) mka_msg;
12585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body_len = get_mka_param_body_len(hdr);
12595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body = (struct ieee802_1x_mka_sak_use_body *) mka_msg;
12605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_mka_dump_sak_use_body(body);
12615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
12625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if ((body_len != 0) && (body_len < 40)) {
12635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR,
12645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   "KaY: MKA Use SAK Packet Body Length (%d bytes) should be 0, 40, or more octets",
12655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   (int) body_len);
12665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
12675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
12685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
12695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* TODO: what action should I take when peer does not support MACsec */
12705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (body_len == 0) {
12715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_WARNING, "KaY: Peer does not support MACsec");
12725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return 0;
12735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
12745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
12755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* TODO: when the plain tx or rx of peer is true, should I change
12765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 * the attribute of controlled port
12775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 */
12785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (body->prx)
12795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_WARNING, "KaY: peer's plain rx are TRUE");
12805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
12815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (body->ptx)
12825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_WARNING, "KaY: peer's plain tx are TRUE");
12835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
12845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* check latest key is valid */
12855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (body->ltx || body->lrx) {
12865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		founded = FALSE;
12875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_memcpy(ki.mi, body->lsrv_mi, sizeof(ki.mi));
12885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ki.kn = ntohl(body->lkn);
12895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		dl_list_for_each(sa_key, &participant->sak_list,
12905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				 struct data_key, list) {
12915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			if (is_ki_equal(&sa_key->key_identifier, &ki)) {
12925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				founded = TRUE;
12935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				break;
12945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			}
12955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
12965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (!founded) {
12975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			wpa_printf(MSG_WARNING, "KaY: Latest key is invalid");
12985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			return -1;
12995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
13005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (os_memcmp(participant->lki.mi, body->lsrv_mi,
13015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			      sizeof(participant->lki.mi)) == 0 &&
13025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		    ntohl(body->lkn) == participant->lki.kn &&
13035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		    body->lan == participant->lan) {
13045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			peer->sak_used = TRUE;
13055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
13065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (body->ltx && peer->is_key_server) {
13075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_cp_set_servertransmitting(
13085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				participant->kay->cp, TRUE);
13095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_cp_sm_step(participant->kay->cp);
13105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
13115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
13125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
13135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* check old key is valid */
13145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (body->otx || body->orx) {
13155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (os_memcmp(participant->oki.mi, body->osrv_mi,
13165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			      sizeof(participant->oki.mi)) != 0 ||
13175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		    ntohl(body->okn) != participant->oki.kn ||
13185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		    body->oan != participant->oan) {
13195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			wpa_printf(MSG_WARNING, "KaY: Old key is invalid");
13205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			return -1;
13215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
13225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
13235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
13245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* TODO: how to set the MACsec hardware when delay_protect is true */
13255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (body->delay_protect && (!ntohl(body->llpn) || !ntohl(body->olpn))) {
13265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_WARNING,
13275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   "KaY: Lowest packet number should greater than 0 when delay_protect is TRUE");
13285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
13295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
13305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
13315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* check all live peer have used the sak for receiving sa */
13325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	all_receiving = TRUE;
13335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(peer, &participant->live_peers,
13345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			 struct ieee802_1x_kay_peer, list) {
13355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (!peer->sak_used) {
13365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			all_receiving = FALSE;
13375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			break;
13385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
13395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
13405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (all_receiving) {
13415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->to_dist_sak = FALSE;
13425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_cp_set_allreceiving(participant->kay->cp, TRUE);
13435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_cp_sm_step(participant->kay->cp);
13445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
13455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
13465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* if i'm key server, and detects peer member pn exhaustion, rekey.*/
13475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	lpn = ntohl(body->llpn);
13485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (lpn > participant->kay->pn_exhaustion) {
13495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (participant->is_key_server) {
13505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->new_sak = TRUE;
13515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			wpa_printf(MSG_WARNING, "KaY: Peer LPN exhaustion");
13525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
13535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
13545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
13555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	founded = FALSE;
13565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(txsa, &participant->txsc->sa_list,
13575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			 struct transmit_sa, list) {
13585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (sa_key != NULL && txsa->pkey == sa_key) {
13595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			founded = TRUE;
13605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			break;
13615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
13625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
13635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!founded) {
13645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_WARNING, "KaY: Can't find txsa");
13655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
13665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
13675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
13685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* FIXME: Secy creates txsa with default npn. If MKA detected Latest Key
13695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 * npn is larger than txsa's npn, set it to txsa.
13705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 */
13715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	secy_get_transmit_next_pn(participant->kay, txsa);
13725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (lpn > txsa->next_pn) {
13735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		secy_set_transmit_next_pn(participant->kay, txsa);
13745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_INFO, "KaY: update lpn =0x%x", lpn);
13755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
13765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
13775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
13785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
13795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
13805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
13815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
13825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_dist_sak_body_present
13835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
13845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic Boolean
13855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_dist_sak_body_present(
13865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant)
13875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
13885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!participant->to_dist_sak || !participant->new_key)
13895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return FALSE;
13905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
13915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return TRUE;
13925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
13935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
13945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
13955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
13965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_get_dist_sak_length
13975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
13985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
13995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_get_dist_sak_length(
14005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant)
14015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
14025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	int length;
14035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	int cs_index = participant->kay->macsec_csindex;
14045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
14055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (participant->advised_desired) {
14065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		length = sizeof(struct ieee802_1x_mka_dist_sak_body);
14075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (cs_index != DEFAULT_CS_INDEX)
14085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			length += CS_ID_LEN;
14095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
14105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		length += cipher_suite_tbl[cs_index].sak_len + 8;
14115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	} else {
14125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		length = MKA_HDR_LEN;
14135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
14145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	length = (length + 0x3) & ~0x3;
14155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
14165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return length;
14175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
14185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
14195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
14205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
14215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_encode_dist_sak_body -
14225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
14235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
14245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_encode_dist_sak_body(
14255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant,
14265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct wpabuf *buf)
14275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
14285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_dist_sak_body *body;
14295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct data_key *sak;
14305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	unsigned int length;
14315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	int cs_index;
14325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	int sak_pos;
14335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
14345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	length = ieee802_1x_mka_get_dist_sak_length(participant);
14355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body = wpabuf_put(buf, length);
14365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body->type = MKA_DISTRIBUTED_SAK;
14375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	set_mka_param_body_len(body, length - MKA_HDR_LEN);
14385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (length == MKA_HDR_LEN) {
14395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body->confid_offset = 0;
14405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body->dan = 0;
14415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return 0;
14425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
14435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
14445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	sak = participant->new_key;
14455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body->confid_offset = sak->confidentiality_offset;
14465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body->dan = sak->an;
14475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body->kn = host_to_be32(sak->key_identifier.kn);
14485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	cs_index = participant->kay->macsec_csindex;
14495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	sak_pos = 0;
14505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (cs_index != DEFAULT_CS_INDEX) {
14515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_memcpy(body->sak, cipher_suite_tbl[cs_index].id, CS_ID_LEN);
14525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		sak_pos = CS_ID_LEN;
14535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
14549ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt	if (aes_wrap(participant->kek.key, 16,
14555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		     cipher_suite_tbl[cs_index].sak_len / 8,
14565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		     sak->key, body->sak + sak_pos)) {
14575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY: AES wrap failed");
14585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
14595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
14605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
14615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_mka_dump_dist_sak_body(body);
14625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
14635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
14645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
14655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
14665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
14675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
14685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_init_data_key -
14695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
14705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic struct data_key *
14715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_init_data_key(const struct key_conf *conf)
14725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
14735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct data_key *pkey;
14745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
14755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!conf)
14765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return NULL;
14775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
14785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	pkey = os_zalloc(sizeof(*pkey));
14795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (pkey == NULL) {
14805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "%s: out of memory", __func__);
14815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return NULL;
14825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
14835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
14845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	pkey->key = os_zalloc(conf->key_len);
14855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (pkey->key == NULL) {
14865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "%s: out of memory", __func__);
14875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(pkey);
14885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return NULL;
14895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
14905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
14915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(pkey->key, conf->key, conf->key_len);
14925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(&pkey->key_identifier, &conf->ki,
14935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		  sizeof(pkey->key_identifier));
14945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	pkey->confidentiality_offset = conf->offset;
14955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	pkey->an = conf->an;
14965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	pkey->transmits = conf->tx;
14975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	pkey->receives = conf->rx;
14985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_get_time(&pkey->created_time);
14995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
15005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	pkey->user = 1;
15015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
15025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return pkey;
15035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
15045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
15055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
15065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
15075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_decode_dist_sak_body -
15085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
15095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
15105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_decode_dist_sak_body(
15115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant,
15125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	const u8 *mka_msg, size_t msg_len)
15135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
15145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_hdr *hdr;
15155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_dist_sak_body *body;
15165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay_peer *peer;
15175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct macsec_ciphersuite *cs;
15185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t body_len;
15195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct key_conf *conf;
15205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct data_key *sa_key = NULL;
15215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_ki sak_ki;
15225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	int sak_len;
15235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	u8 *wrap_sak;
15245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	u8 *unwrap_sak;
15255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
15265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	hdr = (struct ieee802_1x_mka_hdr *) mka_msg;
15275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body_len = get_mka_param_body_len(hdr);
15285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if ((body_len != 0) && (body_len != 28) && (body_len < 36)) {
15295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR,
15305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   "KaY: MKA Use SAK Packet Body Length (%d bytes) should be 0, 28, 36, or more octets",
15315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   (int) body_len);
15325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
15335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
15345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
15355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!participant->principal) {
15365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR,
15375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   "KaY: I can't accept the distributed SAK as I am not principal");
15385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
15395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
15405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (participant->is_key_server) {
15415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR,
15425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   "KaY: I can't accept the distributed SAK as myself is key server ");
15435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
15445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
15455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!participant->kay->macsec_desired ||
15465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	    participant->kay->macsec_capable == MACSEC_CAP_NOT_IMPLEMENTED) {
15475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR,
15485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   "KaY: I am not MACsec-desired or without MACsec capable");
15495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
15505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
15515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
15525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	peer = ieee802_1x_kay_get_live_peer(participant,
15535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					    participant->current_peer_id.mi);
15545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!peer) {
15555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR,
15565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   "KaY: The key server is not in my live peers list");
15575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
15585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
15595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (os_memcmp(&participant->kay->key_server_sci,
15605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		      &peer->sci, sizeof(struct ieee802_1x_mka_sci)) != 0) {
15615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY: The key server is not elected");
15625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
15635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
15645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (body_len == 0) {
15655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->kay->authenticated = TRUE;
15665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->kay->secured = FALSE;
15675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->kay->failed = FALSE;
15685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->advised_desired = FALSE;
15695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_cp_connect_authenticated(participant->kay->cp);
15705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_cp_sm_step(participant->kay->cp);
15715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_WARNING, "KaY:The Key server advise no MACsec");
15725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->to_use_sak = TRUE;
15735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return 0;
15745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
15755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->advised_desired = TRUE;
15765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->kay->authenticated = FALSE;
15775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->kay->secured = TRUE;
15785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->kay->failed = FALSE;
15795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_cp_connect_secure(participant->kay->cp);
15805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_cp_sm_step(participant->kay->cp);
15815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
15825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body = (struct ieee802_1x_mka_dist_sak_body *)mka_msg;
15835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_mka_dump_dist_sak_body(body);
15845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(sa_key, &participant->sak_list, struct data_key, list)
15855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	{
15865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (os_memcmp(sa_key->key_identifier.mi,
15875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			      participant->current_peer_id.mi, MI_LEN) == 0 &&
15885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		    sa_key->key_identifier.kn == be_to_host32(body->kn)) {
15895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			wpa_printf(MSG_WARNING, "KaY:The Key has installed");
15905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			return 0;
15915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
15925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
15935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (body_len == 28) {
15945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		sak_len = DEFAULT_SA_KEY_LEN;
15955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wrap_sak =  body->sak;
15965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->kay->macsec_csindex = DEFAULT_CS_INDEX;
15975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	} else {
15985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		cs = ieee802_1x_kay_get_cipher_suite(participant, body->sak);
15995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (!cs) {
16005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			wpa_printf(MSG_ERROR,
16015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				   "KaY: I can't support the Cipher Suite advised by key server");
16025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			return -1;
16035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
16045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		sak_len = cs->sak_len;
16055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wrap_sak = body->sak + CS_ID_LEN;
16065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->kay->macsec_csindex = cs->index;
16075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
16085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
16095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	unwrap_sak = os_zalloc(sak_len);
16105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!unwrap_sak) {
16115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY-%s: Out of memory", __func__);
16125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
16135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
16149ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt	if (aes_unwrap(participant->kek.key, 16, sak_len >> 3, wrap_sak,
16155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		       unwrap_sak)) {
16165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY: AES unwrap failed");
16175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(unwrap_sak);
16185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
16195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
16205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_hexdump(MSG_DEBUG, "\tAES Key Unwrap of SAK:", unwrap_sak, sak_len);
16215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
16225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	conf = os_zalloc(sizeof(*conf));
16235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!conf) {
16245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY-%s: Out of memory", __func__);
16255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(unwrap_sak);
16265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
16275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
16285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	conf->key_len = sak_len;
16295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
16305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	conf->key = os_zalloc(conf->key_len);
16315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!conf->key) {
16325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY-%s: Out of memory", __func__);
16335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(unwrap_sak);
16345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(conf);
16355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
16365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
16375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
16385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(conf->key, unwrap_sak, conf->key_len);
16395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
16405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(&sak_ki.mi, &participant->current_peer_id.mi,
16415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		  sizeof(sak_ki.mi));
16425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	sak_ki.kn = be_to_host32(body->kn);
16435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
16445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(conf->ki.mi, sak_ki.mi, MI_LEN);
16455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	conf->ki.kn = sak_ki.kn;
16465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	conf->an = body->dan;
16475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	conf->offset = body->confid_offset;
16485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	conf->rx = TRUE;
16495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	conf->tx = TRUE;
16505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
16515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	sa_key = ieee802_1x_kay_init_data_key(conf);
16525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!sa_key) {
16535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(unwrap_sak);
16545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(conf->key);
16555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(conf);
16565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
16575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
16585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
16595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_add(&participant->sak_list, &sa_key->list);
16605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
16615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_cp_set_ciphersuite(
16625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->kay->cp,
16635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		cipher_suite_tbl[participant->kay->macsec_csindex].id);
16645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_cp_sm_step(participant->kay->cp);
16655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_cp_set_offset(participant->kay->cp, body->confid_offset);
16665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_cp_sm_step(participant->kay->cp);
16675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_cp_set_distributedki(participant->kay->cp, &sak_ki);
16685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_cp_set_distributedan(participant->kay->cp, body->dan);
16695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_cp_signal_newsak(participant->kay->cp);
16705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_cp_sm_step(participant->kay->cp);
16715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
16725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->to_use_sak = TRUE;
16735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
16745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_free(unwrap_sak);
16755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_free(conf->key);
16765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_free(conf);
16775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
16785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
16795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
16805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
16815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
16825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
16835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_icv_body_present
16845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
16855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic Boolean
16865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_icv_body_present(struct ieee802_1x_mka_participant *participant)
16875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
16885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return TRUE;
16895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
16905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
16915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
16925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
16935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_get_icv_length
16945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
16955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
16965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_get_icv_length(struct ieee802_1x_mka_participant *participant)
16975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
16985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	int length;
16995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
17005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	length = sizeof(struct ieee802_1x_mka_icv_body);
17015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	length += mka_alg_tbl[participant->kay->mka_algindex].icv_len;
17025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
17035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return (length + 0x3) & ~0x3;
17045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
17055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
17065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
17075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
17085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_encode_icv_body -
17095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
17105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
17115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_encode_icv_body(struct ieee802_1x_mka_participant *participant,
17125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			       struct wpabuf *buf)
17135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
17145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_icv_body *body;
17155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	unsigned int length;
17165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	u8 cmac[MAX_ICV_LEN];
17175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
17185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	length = ieee802_1x_mka_get_icv_length(participant);
17195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (length != DEFAULT_ICV_LEN)  {
17205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body = wpabuf_put(buf, MKA_HDR_LEN);
17215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body->type = MKA_ICV_INDICATOR;
17225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		set_mka_param_body_len(body, length - MKA_HDR_LEN);
17235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
17245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
17255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (mka_alg_tbl[participant->kay->mka_algindex].icv_hash(
17265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		    participant->ick.key, wpabuf_head(buf), buf->used, cmac)) {
17275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY, omac1_aes_128 failed");
17285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
17295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
17305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
17315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (length != DEFAULT_ICV_LEN)  {
17325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_memcpy(wpabuf_put(buf, length - MKA_HDR_LEN), cmac,
17335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			  length - MKA_HDR_LEN);
17345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	} else {
17355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_memcpy(wpabuf_put(buf, length), cmac, length);
17365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
17375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
17385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
17395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
17405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
17415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
17425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_decode_icv_body -
17435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
17445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic u8 *
17455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_decode_icv_body(struct ieee802_1x_mka_participant *participant,
17465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			       const u8 *mka_msg, size_t msg_len)
17475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
17485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_hdr *hdr;
17495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_icv_body *body;
17505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t body_len;
17515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t left_len;
17525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	int body_type;
17535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	const u8 *pos;
17545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
17555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	pos = mka_msg;
17565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	left_len = msg_len;
17575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	while (left_len > (MKA_HDR_LEN + DEFAULT_ICV_LEN)) {
17585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		hdr = (struct ieee802_1x_mka_hdr *) pos;
17595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body_len = get_mka_param_body_len(hdr);
17605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body_type = get_mka_param_body_type(hdr);
17615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
17625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (left_len < (body_len + MKA_HDR_LEN))
17635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			break;
17645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
17655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (body_type != MKA_ICV_INDICATOR) {
17665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			left_len -= MKA_HDR_LEN + body_len;
17675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			pos += MKA_HDR_LEN + body_len;
17685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			continue;
17695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
17705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
17715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body = (struct ieee802_1x_mka_icv_body *)pos;
17725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (body_len
17735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			< mka_alg_tbl[participant->kay->mka_algindex].icv_len) {
17745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			return NULL;
17755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
17765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
17775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return body->icv;
17785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
17795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
17805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return (u8 *) (mka_msg + msg_len - DEFAULT_ICV_LEN);
17815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
17825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
17835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
17845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
17855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_decode_dist_cak_body-
17865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
17875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
17885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_decode_dist_cak_body(
17895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant,
17905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	const u8 *mka_msg, size_t msg_len)
17915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
17925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_hdr *hdr;
17935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t body_len;
17945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
17955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	hdr = (struct ieee802_1x_mka_hdr *) mka_msg;
17965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body_len = get_mka_param_body_len(hdr);
17975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (body_len < 28) {
17985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR,
17995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   "KaY: MKA Use SAK Packet Body Length (%d bytes) should be 28 or more octets",
18005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   (int) body_len);
18015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
18025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
18035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
18045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
18055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
18065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
18075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
18085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
18095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_decode_kmd_body -
18105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
18115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
18125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_decode_kmd_body(
18135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant,
18145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	const u8 *mka_msg, size_t msg_len)
18155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
18165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_hdr *hdr;
18175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t body_len;
18185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
18195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	hdr = (struct ieee802_1x_mka_hdr *) mka_msg;
18205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body_len = get_mka_param_body_len(hdr);
18215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (body_len < 5) {
18225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR,
18235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   "KaY: MKA Use SAK Packet Body Length (%d bytes) should be 5 or more octets",
18245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   (int) body_len);
18255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
18265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
18275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
18285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
18295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
18305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
18315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
18325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
18335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_decode_announce_body -
18345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
18355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int ieee802_1x_mka_decode_announce_body(
18365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant,
18375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	const u8 *mka_msg, size_t msg_len)
18385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
18395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
18405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
18415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
18425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
18435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic struct mka_param_body_handler mak_body_handler[] = {
18445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* basic parameter set */
18455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	{
18465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_encode_basic_body,
18475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		NULL,
18485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_basic_body_length,
18495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_basic_body_present
18505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	},
18515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
18525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* live peer list parameter set */
18535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	{
18545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_encode_live_peer_body,
18555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_decode_live_peer_body,
18565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_get_live_peer_length,
18575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_live_peer_body_present
18585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	},
18595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
18605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* potential peer list parameter set */
18615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	{
18625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_encode_potential_peer_body,
18635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_decode_potential_peer_body,
18645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_get_potential_peer_length,
18655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_potential_peer_body_present
18665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	},
18675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
18685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* sak use parameter set */
18695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	{
18705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_encode_sak_use_body,
18715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_decode_sak_use_body,
18725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_get_sak_use_length,
18735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_sak_use_body_present
18745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	},
18755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
18765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* distribute sak parameter set */
18775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	{
18785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_encode_dist_sak_body,
18795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_decode_dist_sak_body,
18805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_get_dist_sak_length,
18815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_dist_sak_body_present
18825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	},
18835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
18845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* distribute cak parameter set */
18855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	{
18865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		NULL,
18875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_decode_dist_cak_body,
18885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		NULL,
18895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		NULL
18905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	},
18915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
18925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* kmd parameter set */
18935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	{
18945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		NULL,
18955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_decode_kmd_body,
18965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		NULL,
18975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		NULL
18985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	},
18995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
19005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* announce parameter set */
19015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	{
19025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		NULL,
19035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_decode_announce_body,
19045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		NULL,
19055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		NULL
19065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	},
19075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
19085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* icv parameter set */
19095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	{
19105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_encode_icv_body,
19115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		NULL,
19125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_get_icv_length,
19135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_icv_body_present
19145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	},
19155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt};
19165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
19175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
19185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
19195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_deinit_data_key -
19205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
19215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtvoid ieee802_1x_kay_deinit_data_key(struct data_key *pkey)
19225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
19235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!pkey)
19245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return;
19255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
19265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	pkey->user--;
19275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (pkey->user > 1)
19285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return;
19295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
19305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_del(&pkey->list);
19315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_free(pkey->key);
19325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_free(pkey);
19335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
19345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
19355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
19365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
19375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_generate_new_sak -
19385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
19395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
19405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_generate_new_sak(struct ieee802_1x_mka_participant *participant)
19415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
19425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct data_key *sa_key = NULL;
19435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct key_conf *conf;
19445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay_peer *peer;
19455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay *kay = participant->kay;
19465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	int ctx_len, ctx_offset;
19475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	u8 *context;
19485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
19495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* check condition for generating a fresh SAK:
19505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 * must have one live peer
19515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 * and MKA life time elapse since last distribution
19525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 * or potential peer is empty
19535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 */
19545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (dl_list_empty(&participant->live_peers)) {
19555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR,
19565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   "KaY: Live peers list must not empty when generating fresh SAK");
19575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
19585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
19595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
19605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* FIXME: A fresh SAK not generated until
19615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 * the live peer list contains at least one peer and
19625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 * MKA life time has elapsed since the prior SAK was first distributed,
19635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 * or the Key server's potential peer is empty
19645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 * but I can't understand the second item, so
19655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 * here only check first item and ingore
19665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 *   && (!dl_list_empty(&participant->potential_peers))) {
19675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 */
19685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if ((time(NULL) - kay->dist_time) < MKA_LIFE_TIME / 1000) {
19695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR,
19705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   "KaY: Life time have not elapsed since prior SAK distributed");
19715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
19725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
19735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
19745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	conf = os_zalloc(sizeof(*conf));
19755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!conf) {
19765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY-%s: Out of memory", __func__);
19775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
19785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
19795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	conf->key_len = cipher_suite_tbl[kay->macsec_csindex].sak_len;
19805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
19815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	conf->key = os_zalloc(conf->key_len);
19825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!conf->key) {
19835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(conf);
19845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY-%s: Out of memory", __func__);
19855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
19865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
19875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
19885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ctx_len = conf->key_len + sizeof(kay->dist_kn);
19895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(peer, &participant->live_peers,
19905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			 struct ieee802_1x_kay_peer, list)
19915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ctx_len += sizeof(peer->mi);
19925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ctx_len += sizeof(participant->mi);
19935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
19945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	context = os_zalloc(ctx_len);
19955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!context) {
19965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(conf->key);
19975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(conf);
19985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
19995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
20005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ctx_offset = 0;
20015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_get_random(context + ctx_offset, conf->key_len);
20025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ctx_offset += conf->key_len;
20035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(peer, &participant->live_peers,
20045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			 struct ieee802_1x_kay_peer, list) {
20055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_memcpy(context + ctx_offset, peer->mi, sizeof(peer->mi));
20065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ctx_offset += sizeof(peer->mi);
20075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
20085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(context + ctx_offset, participant->mi,
20095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		  sizeof(participant->mi));
20105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ctx_offset += sizeof(participant->mi);
20115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(context + ctx_offset, &kay->dist_kn, sizeof(kay->dist_kn));
20125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
20135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (conf->key_len == 16) {
20145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_sak_128bits_aes_cmac(participant->cak.key,
20155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt						context, ctx_len, conf->key);
20165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	} else if (conf->key_len == 32) {
20175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_sak_128bits_aes_cmac(participant->cak.key,
20185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt						context, ctx_len, conf->key);
20195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	} else {
20205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY: SAK Length not support");
20215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(conf->key);
20225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(conf);
20235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(context);
20245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
20255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
20265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_hexdump(MSG_DEBUG, "KaY: generated new SAK",
20275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		    conf->key, conf->key_len);
20285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
20295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(conf->ki.mi, participant->mi, MI_LEN);
20305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	conf->ki.kn = participant->kay->dist_kn;
20315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	conf->an = participant->kay->dist_an;
20325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	conf->offset = kay->macsec_confidentiality;
20335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	conf->rx = TRUE;
20345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	conf->tx = TRUE;
20355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
20365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	sa_key = ieee802_1x_kay_init_data_key(conf);
20375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!sa_key) {
20385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(conf->key);
20395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(conf);
20405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(context);
20415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
20425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
20435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->new_key = sa_key;
20445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
20455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_add(&participant->sak_list, &sa_key->list);
20465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_cp_set_ciphersuite(participant->kay->cp,
20475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				      cipher_suite_tbl[kay->macsec_csindex].id);
20485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_cp_sm_step(kay->cp);
20495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_cp_set_offset(kay->cp, conf->offset);
20505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_cp_sm_step(kay->cp);
20515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_cp_set_distributedki(kay->cp, &conf->ki);
20525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_cp_set_distributedan(kay->cp, conf->an);
20535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_cp_signal_newsak(kay->cp);
20545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_cp_sm_step(kay->cp);
20555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
20565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(peer, &participant->live_peers,
20575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			 struct ieee802_1x_kay_peer, list)
20585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		peer->sak_used = FALSE;
20595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
20605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->kay->dist_kn++;
20615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->kay->dist_an++;
20625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (participant->kay->dist_an > 3)
20635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->kay->dist_an = 0;
20645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
20655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->kay->dist_time = time(NULL);
20665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
20675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_free(conf->key);
20685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_free(conf);
20695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_free(context);
20705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
20715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
20725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
20735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
20745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
20755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_elect_key_server - elect the key server
20765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * when to elect: whenever the live peers list changes
20775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
20785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
20795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_elect_key_server(struct ieee802_1x_mka_participant *participant)
20805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
20815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay_peer *peer;
20825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay_peer *key_server = NULL;
20835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay *kay = participant->kay;
20845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	Boolean i_is_key_server;
20855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	int i;
20865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
20875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (participant->is_obliged_key_server) {
20885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->new_sak = TRUE;
20895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->to_dist_sak = FALSE;
20905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_cp_set_electedself(kay->cp, TRUE);
20915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return 0;
20925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
20935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
20945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* elect the key server among the peers */
20955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(peer, &participant->live_peers,
20965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			 struct ieee802_1x_kay_peer, list) {
20975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (!peer->is_key_server)
20985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			continue;
20995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
21005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (!key_server) {
21015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			key_server = peer;
21025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			continue;
21035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
21045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
21055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (peer->key_server_priority <
21065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		    key_server->key_server_priority) {
21075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			key_server = peer;
21085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		} else if (peer->key_server_priority ==
21095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   key_server->key_server_priority) {
21105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			for (i = 0; i < 6; i++) {
21115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				if (peer->sci.addr[i] <
21125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				    key_server->sci.addr[i])
21135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					key_server = peer;
21145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			}
21155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
21165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
21175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
21185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* elect the key server between me and the above elected peer */
21195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	i_is_key_server = FALSE;
21205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (key_server && participant->can_be_key_server) {
21215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (kay->actor_priority
21225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   < key_server->key_server_priority) {
21235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			i_is_key_server = TRUE;
21245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		} else if (kay->actor_priority
21255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					== key_server->key_server_priority) {
21265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			for (i = 0; i < 6; i++) {
21275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				if (kay->actor_sci.addr[i]
21285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					< key_server->sci.addr[i]) {
21295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					i_is_key_server = TRUE;
21305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				}
21315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			}
21325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
21335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
21345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
21355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!key_server && !i_is_key_server) {
21365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->principal = FALSE;
21375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->is_key_server = FALSE;
21385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->is_elected = FALSE;
21395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return 0;
21405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
21415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
21425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (i_is_key_server) {
21435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_cp_set_electedself(kay->cp, TRUE);
21445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (os_memcmp(&kay->key_server_sci, &kay->actor_sci,
21455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			      sizeof(kay->key_server_sci))) {
21465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_cp_signal_chgdserver(kay->cp);
21475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_cp_sm_step(kay->cp);
21485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
21495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
21505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->is_key_server = TRUE;
21515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->principal = TRUE;
21525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->new_sak = TRUE;
21535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_DEBUG, "KaY: I is elected as key server");
21545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->to_dist_sak = FALSE;
21555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->is_elected = TRUE;
21565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
21575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_memcpy(&kay->key_server_sci, &kay->actor_sci,
21585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			  sizeof(kay->key_server_sci));
21595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->key_server_priority = kay->actor_priority;
21605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
21615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
21625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (key_server) {
21635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_cp_set_electedself(kay->cp, FALSE);
21645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (os_memcmp(&kay->key_server_sci, &key_server->sci,
21655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			      sizeof(kay->key_server_sci))) {
21665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_cp_signal_chgdserver(kay->cp);
21675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_cp_sm_step(kay->cp);
21685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
21695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
21705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->is_key_server = FALSE;
21715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->principal = TRUE;
21725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->is_elected = TRUE;
21735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
21745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_memcpy(&kay->key_server_sci, &key_server->sci,
21755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			  sizeof(kay->key_server_sci));
21765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->key_server_priority = key_server->key_server_priority;
21775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
21785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
21795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
21805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
21815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
21825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
21835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
21845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_decide_macsec_use - the key server determinate
21855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt *		 how to use MACsec: whether use MACsec and its capability
21865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * protectFrames will be advised if the key server and one of its live peers are
21875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * MACsec capable and one of those request MACsec protection
21885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
21895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
21905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_decide_macsec_use(
21915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant)
21925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
21935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay *kay = participant->kay;
21945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay_peer *peer;
21955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	enum macsec_cap less_capability;
21965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	Boolean has_peer;
21975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
21985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!participant->is_key_server)
21995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
22005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
22015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* key server self is MACsec-desired and requesting MACsec */
22025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!kay->macsec_desired) {
22035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->advised_desired = FALSE;
22045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
22055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
22065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (kay->macsec_capable == MACSEC_CAP_NOT_IMPLEMENTED) {
22075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->advised_desired = FALSE;
22085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
22095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
22105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	less_capability = kay->macsec_capable;
22115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
22125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* at least one of peers is MACsec-desired and requesting MACsec */
22135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	has_peer = FALSE;
22145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(peer, &participant->live_peers,
22155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			 struct ieee802_1x_kay_peer, list) {
22165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (!peer->macsec_desired)
22175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			continue;
22185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
22195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (peer->macsec_capbility == MACSEC_CAP_NOT_IMPLEMENTED)
22205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			continue;
22215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
22225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		less_capability = (less_capability < peer->macsec_capbility) ?
22235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			less_capability : peer->macsec_capbility;
22245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		has_peer = TRUE;
22255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
22265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
22275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (has_peer) {
22285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->advised_desired = TRUE;
22295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->advised_capability = less_capability;
22305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->authenticated = FALSE;
22315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->secured = TRUE;
22325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->failed = FALSE;
22335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_cp_connect_secure(kay->cp);
22345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_cp_sm_step(kay->cp);
22355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	} else {
22365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->advised_desired = FALSE;
22375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->advised_capability = MACSEC_CAP_NOT_IMPLEMENTED;
22385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->to_use_sak = FALSE;
22395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->authenticated = TRUE;
22405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->secured = FALSE;
22415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->failed = FALSE;
22425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->ltx_kn = 0;
22435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->ltx_an = 0;
22445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->lrx_kn = 0;
22455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->lrx_an = 0;
22465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->otx_kn = 0;
22475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->otx_an = 0;
22485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->orx_kn = 0;
22495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->orx_an = 0;
22505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_cp_connect_authenticated(kay->cp);
22515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_cp_sm_step(kay->cp);
22525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
22535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
22545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
22555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
22565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
22575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic const u8 pae_group_addr[ETH_ALEN] = {
22585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	0x01, 0x80, 0xc2, 0x00, 0x00, 0x03
22595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt};
22605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
22615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
22625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
22635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_encode_mkpdu -
22645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
22655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
22665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_encode_mkpdu(struct ieee802_1x_mka_participant *participant,
22675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			    struct wpabuf *pbuf)
22685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
22695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	unsigned int i;
22705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee8023_hdr *ether_hdr;
22715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_hdr *eapol_hdr;
22725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
22735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ether_hdr = wpabuf_put(pbuf, sizeof(*ether_hdr));
22745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(ether_hdr->dest, pae_group_addr, sizeof(ether_hdr->dest));
22755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(ether_hdr->src, participant->kay->actor_sci.addr,
22765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		  sizeof(ether_hdr->dest));
22775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ether_hdr->ethertype = host_to_be16(ETH_P_EAPOL);
22785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
22795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	eapol_hdr = wpabuf_put(pbuf, sizeof(*eapol_hdr));
22805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	eapol_hdr->version = EAPOL_VERSION;
22815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	eapol_hdr->type = IEEE802_1X_TYPE_EAPOL_MKA;
22825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	eapol_hdr->length = host_to_be16(pbuf->size - pbuf->used);
22835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
22845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	for (i = 0; i < ARRAY_SIZE(mak_body_handler); i++) {
22855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (mak_body_handler[i].body_present &&
22865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		    mak_body_handler[i].body_present(participant)) {
22875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			if (mak_body_handler[i].body_tx(participant, pbuf))
22885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				return -1;
22895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
22905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
22915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
22925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
22935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
22945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
22955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
22965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_participant_send_mkpdu -
22975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
22985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
22995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_participant_send_mkpdu(
23005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant)
23015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
23025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct wpabuf *buf;
23035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay *kay = participant->kay;
23045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t length = 0;
23055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	unsigned int i;
23065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
23075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "KaY: to enpacket and send the MKPDU");
23085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	length += sizeof(struct ieee802_1x_hdr) + sizeof(struct ieee8023_hdr);
23095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	for (i = 0; i < ARRAY_SIZE(mak_body_handler); i++) {
23105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (mak_body_handler[i].body_present &&
23115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		    mak_body_handler[i].body_present(participant))
23125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			length += mak_body_handler[i].body_length(participant);
23135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
23145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
23155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	buf = wpabuf_alloc(length);
23165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!buf) {
23175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY: out of memory");
23185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
23195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
23205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
23215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (ieee802_1x_kay_encode_mkpdu(participant, buf)) {
23225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY: encode mkpdu fail!");
23235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
23245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
23255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
23265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	l2_packet_send(kay->l2_mka, NULL, 0, wpabuf_head(buf), wpabuf_len(buf));
23275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpabuf_free(buf);
23285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
23295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->active = TRUE;
23305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->active = TRUE;
23315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
23325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
23335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
23345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
23355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
23365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic void ieee802_1x_kay_deinit_transmit_sa(struct transmit_sa *psa);
23375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
23385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_participant_timer -
23395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
23405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic void ieee802_1x_participant_timer(void *eloop_ctx, void *timeout_ctx)
23415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
23425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant;
23435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay *kay;
23445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay_peer *peer, *pre_peer;
23455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	time_t now = time(NULL);
23465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	Boolean lp_changed;
23475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct receive_sc *rxsc, *pre_rxsc;
23485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct transmit_sa *txsa, *pre_txsa;
23495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
23505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant = (struct ieee802_1x_mka_participant *)eloop_ctx;
23515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay = participant->kay;
23525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (participant->cak_life) {
23535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (now > participant->cak_life) {
23545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			kay->authenticated = FALSE;
23555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			kay->secured = FALSE;
23565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			kay->failed = TRUE;
23575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_kay_delete_mka(kay, &participant->ckn);
23585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			return;
23595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
23605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
23615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
23625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* should delete MKA instance if there are not live peers
23635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 * when the MKA life elapsed since its creating */
23645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (participant->mka_life) {
23655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (dl_list_empty(&participant->live_peers)) {
23665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			if (now > participant->mka_life) {
23675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				kay->authenticated = FALSE;
23685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				kay->secured = FALSE;
23695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				kay->failed = TRUE;
23705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				ieee802_1x_kay_delete_mka(kay,
23715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt							  &participant->ckn);
23725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				return;
23735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			}
23745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		} else {
23755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->mka_life = 0;
23765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
23775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
23785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
23795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	lp_changed = FALSE;
23805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each_safe(peer, pre_peer, &participant->live_peers,
23815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			      struct ieee802_1x_kay_peer, list) {
23825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (now > peer->expire) {
23835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			wpa_printf(MSG_DEBUG, "KaY: Live peer removed");
23845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			wpa_hexdump(MSG_DEBUG, "\tMI: ", peer->mi,
23855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				    sizeof(peer->mi));
23865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			wpa_printf(MSG_DEBUG, "\tMN: %d", peer->mn);
23875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			dl_list_for_each_safe(rxsc, pre_rxsc,
23885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					      &participant->rxsc_list,
23895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					      struct receive_sc, list) {
23905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				if (os_memcmp(&rxsc->sci, &peer->sci,
23915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					      sizeof(rxsc->sci)) == 0) {
23925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					secy_delete_receive_sc(kay, rxsc);
23935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					ieee802_1x_kay_deinit_receive_sc(
23945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt						participant, rxsc);
23955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				}
23965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			}
23975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			dl_list_del(&peer->list);
23985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			os_free(peer);
23995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			lp_changed = TRUE;
24005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
24015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
24025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
24035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (lp_changed) {
24045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (dl_list_empty(&participant->live_peers)) {
24055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->advised_desired = FALSE;
24065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->advised_capability =
24075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				MACSEC_CAP_NOT_IMPLEMENTED;
24085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->to_use_sak = FALSE;
24095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			kay->authenticated = TRUE;
24105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			kay->secured = FALSE;
24115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			kay->failed = FALSE;
24125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			kay->ltx_kn = 0;
24135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			kay->ltx_an = 0;
24145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			kay->lrx_kn = 0;
24155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			kay->lrx_an = 0;
24165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			kay->otx_kn = 0;
24175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			kay->otx_an = 0;
24185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			kay->orx_kn = 0;
24195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			kay->orx_an = 0;
24205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			dl_list_for_each_safe(txsa, pre_txsa,
24215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					      &participant->txsc->sa_list,
24225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					      struct transmit_sa, list) {
24235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				secy_disable_transmit_sa(kay, txsa);
24245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				ieee802_1x_kay_deinit_transmit_sa(txsa);
24255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			}
24265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
24275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_cp_connect_authenticated(kay->cp);
24285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_cp_sm_step(kay->cp);
24295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		} else {
24305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_kay_elect_key_server(participant);
24315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_kay_decide_macsec_use(participant);
24325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
24335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
24345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
24355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each_safe(peer, pre_peer, &participant->potential_peers,
24365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			      struct ieee802_1x_kay_peer, list) {
24375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (now > peer->expire) {
24385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			wpa_printf(MSG_DEBUG, "KaY: Potential peer removed");
24395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			wpa_hexdump(MSG_DEBUG, "\tMI: ", peer->mi,
24405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				    sizeof(peer->mi));
24415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			wpa_printf(MSG_DEBUG, "\tMN: %d", peer->mn);
24425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			dl_list_del(&peer->list);
24435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			os_free(peer);
24445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
24455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
24465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
24475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (participant->new_sak) {
24485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (!ieee802_1x_kay_generate_new_sak(participant))
24495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->to_dist_sak = TRUE;
24505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
24515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->new_sak = FALSE;
24525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
24535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
24545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (participant->retry_count < MAX_RETRY_CNT) {
24555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_participant_send_mkpdu(participant);
24565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->retry_count++;
24575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
24585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
24595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	eloop_register_timeout(MKA_HELLO_TIME / 1000, 0,
24605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			       ieee802_1x_participant_timer,
24615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			       participant, NULL);
24625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
24635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
24645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
24655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
24665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_init_transmit_sa -
24675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
24685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic struct transmit_sa *
24695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_init_transmit_sa(struct transmit_sc *psc, u8 an, u32 next_PN,
24705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				struct data_key *key)
24715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
24725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct transmit_sa *psa;
24735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
24745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	key->tx_latest = TRUE;
24755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	key->rx_latest = TRUE;
24765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
24775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	psa = os_zalloc(sizeof(*psa));
24785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!psa) {
24795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "%s: out of memory", __func__);
24805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return NULL;
24815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
24825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
24835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (key->confidentiality_offset >= CONFIDENTIALITY_OFFSET_0 &&
24845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	    key->confidentiality_offset <= CONFIDENTIALITY_OFFSET_50)
24855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		psa->confidentiality = TRUE;
24865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	else
24875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		psa->confidentiality = FALSE;
24885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
24895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	psa->an = an;
24905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	psa->pkey = key;
24915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	psa->next_pn = next_PN;
24925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	psa->sc = psc;
24935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
24945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_get_time(&psa->created_time);
24955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	psa->in_use = FALSE;
24965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
24975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_add(&psc->sa_list, &psa->list);
24985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG,
24995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		   "KaY: Create transmit SA(an: %d, next_PN: %u) of SC(channel: %d)",
25005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		   (int) an, next_PN, psc->channel);
25015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
25025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return psa;
25035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
25045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
25055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
25065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
25075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_deinit_transmit_sa -
25085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
25095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic void ieee802_1x_kay_deinit_transmit_sa(struct transmit_sa *psa)
25105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
25115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	psa->pkey = NULL;
25125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG,
25135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		   "KaY: Delete transmit SA(an: %d) of SC(channel: %d)",
25145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		   psa->an, psa->sc->channel);
25155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_del(&psa->list);
25165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_free(psa);
25175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
25185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
25195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
25205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
25215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * init_transmit_sc -
25225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
25235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic struct transmit_sc *
25245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_init_transmit_sc(const struct ieee802_1x_mka_sci *sci,
25255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				int channel)
25265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
25275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct transmit_sc *psc;
25285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
25295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	psc = os_zalloc(sizeof(*psc));
25305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!psc) {
25315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "%s: out of memory", __func__);
25325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return NULL;
25335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
25345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(&psc->sci, sci, sizeof(psc->sci));
25355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	psc->channel = channel;
25365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
25375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_get_time(&psc->created_time);
25385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	psc->transmitting = FALSE;
25395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	psc->encoding_sa = FALSE;
25405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	psc->enciphering_sa = FALSE;
25415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
25425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_init(&psc->sa_list);
25435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "KaY: Create transmit SC(channel: %d)", channel);
25445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_hexdump(MSG_DEBUG, "SCI: ", (u8 *)sci , sizeof(*sci));
25455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
25465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return psc;
25475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
25485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
25495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
25505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
25515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_deinit_transmit_sc -
25525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
25535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic void
25545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_deinit_transmit_sc(
25555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant, struct transmit_sc *psc)
25565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
25575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct transmit_sa *psa, *tmp;
25585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
25595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "KaY: Delete transmit SC(channel: %d)",
25605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		   psc->channel);
25615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each_safe(psa, tmp, &psc->sa_list, struct transmit_sa,
25625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			      list) {
25635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		secy_disable_transmit_sa(participant->kay, psa);
25645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_kay_deinit_transmit_sa(psa);
25655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
25665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
25675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_free(psc);
25685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
25695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
25705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
25715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/****************** Interface between CP and KAY *********************/
25725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
25735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_set_latest_sa_attr -
25745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
25755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtint ieee802_1x_kay_set_latest_sa_attr(struct ieee802_1x_kay *kay,
25765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				      struct ieee802_1x_mka_ki *lki, u8 lan,
25775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				      Boolean ltx, Boolean lrx)
25785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
25795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *principal;
25805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
25815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	principal = ieee802_1x_kay_get_principal_participant(kay);
25825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!principal)
25835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
25845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
25855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!lki)
25865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_memset(&principal->lki, 0, sizeof(principal->lki));
25875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	else
25885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_memcpy(&principal->lki, lki, sizeof(principal->lki));
25895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
25905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	principal->lan = lan;
25915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	principal->ltx = ltx;
25925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	principal->lrx = lrx;
25935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!lki) {
25945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->ltx_kn = 0;
25955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->lrx_kn = 0;
25965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	} else {
25975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->ltx_kn = lki->kn;
25985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->lrx_kn = lki->kn;
25995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
26005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->ltx_an = lan;
26015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->lrx_an = lan;
26025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
26035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
26045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
26055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
26065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
26075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
26085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_set_old_sa_attr -
26095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
26105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtint ieee802_1x_kay_set_old_sa_attr(struct ieee802_1x_kay *kay,
26115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				   struct ieee802_1x_mka_ki *oki,
26125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				   u8 oan, Boolean otx, Boolean orx)
26135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
26145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *principal;
26155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
26165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	principal = ieee802_1x_kay_get_principal_participant(kay);
26175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!principal)
26185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
26195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
26205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!oki)
26215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_memset(&principal->oki, 0, sizeof(principal->oki));
26225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	else
26235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_memcpy(&principal->oki, oki, sizeof(principal->oki));
26245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
26255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	principal->oan = oan;
26265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	principal->otx = otx;
26275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	principal->orx = orx;
26285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
26295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!oki) {
26305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->otx_kn = 0;
26315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->orx_kn = 0;
26325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	} else {
26335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->otx_kn = oki->kn;
26345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->orx_kn = oki->kn;
26355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
26365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->otx_an = oan;
26375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->orx_an = oan;
26385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
26395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
26405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
26415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
26425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
26435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
26445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_create_sas -
26455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
26465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtint ieee802_1x_kay_create_sas(struct ieee802_1x_kay *kay,
26475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			      struct ieee802_1x_mka_ki *lki)
26485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
26495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct data_key *sa_key, *latest_sak;
26505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *principal;
26515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct receive_sc *rxsc;
26525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct receive_sa *rxsa;
26535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct transmit_sa *txsa;
26545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
26555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	principal = ieee802_1x_kay_get_principal_participant(kay);
26565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!principal)
26575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
26585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
26595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	latest_sak = NULL;
26605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(sa_key, &principal->sak_list, struct data_key, list) {
26615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (is_ki_equal(&sa_key->key_identifier, lki)) {
26625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			sa_key->rx_latest = TRUE;
26635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			sa_key->tx_latest = TRUE;
26645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			latest_sak = sa_key;
26655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			principal->to_use_sak = TRUE;
26665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		} else {
26675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			sa_key->rx_latest = FALSE;
26685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			sa_key->tx_latest = FALSE;
26695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
26705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
26715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!latest_sak) {
26725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "lki related sak not found");
26735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
26745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
26755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
26765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(rxsc, &principal->rxsc_list, struct receive_sc, list) {
26775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		rxsa = ieee802_1x_kay_init_receive_sa(rxsc, latest_sak->an, 1,
26785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt						      latest_sak);
26795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (!rxsa)
26805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			return -1;
26815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
26825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		secy_create_receive_sa(kay, rxsa);
26835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
26845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
26855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	txsa = ieee802_1x_kay_init_transmit_sa(principal->txsc, latest_sak->an,
26865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					       1, latest_sak);
26875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!txsa)
26885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
26895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
26905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	secy_create_transmit_sa(kay, txsa);
26915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
26925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
26935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
26945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
26955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
26965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
26975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
26985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
26995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_delete_sas -
27005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
27015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtint ieee802_1x_kay_delete_sas(struct ieee802_1x_kay *kay,
27025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			      struct ieee802_1x_mka_ki *ki)
27035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
27045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct data_key *sa_key, *pre_key;
27055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct transmit_sa *txsa, *pre_txsa;
27065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct receive_sa *rxsa, *pre_rxsa;
27075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct receive_sc *rxsc;
27085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *principal;
27095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
27105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "KaY: Entry into %s", __func__);
27115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	principal = ieee802_1x_kay_get_principal_participant(kay);
27125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!principal)
27135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
27145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
27155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* remove the transmit sa */
27165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each_safe(txsa, pre_txsa, &principal->txsc->sa_list,
27175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			      struct transmit_sa, list) {
27185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (is_ki_equal(&txsa->pkey->key_identifier, ki)) {
27195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			secy_disable_transmit_sa(kay, txsa);
27205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_kay_deinit_transmit_sa(txsa);
27215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
27225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
27235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
27245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* remove the receive sa */
27255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(rxsc, &principal->rxsc_list, struct receive_sc, list) {
27265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		dl_list_for_each_safe(rxsa, pre_rxsa, &rxsc->sa_list,
27275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				      struct receive_sa, list) {
27285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			if (is_ki_equal(&rxsa->pkey->key_identifier, ki)) {
27295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				secy_disable_receive_sa(kay, rxsa);
27305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				ieee802_1x_kay_deinit_receive_sa(rxsa);
27315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			}
27325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
27335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
27345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
27355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* remove the sak */
27365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each_safe(sa_key, pre_key, &principal->sak_list,
27375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			      struct data_key, list) {
27385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (is_ki_equal(&sa_key->key_identifier, ki)) {
27395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_kay_deinit_data_key(sa_key);
27405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			break;
27415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
27425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (principal->new_key == sa_key)
27435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			principal->new_key = NULL;
27445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
27455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
27465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
27475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
27485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
27495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
27505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
27515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_enable_tx_sas -
27525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
27535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtint ieee802_1x_kay_enable_tx_sas(struct ieee802_1x_kay *kay,
27545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				 struct ieee802_1x_mka_ki *lki)
27555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
27565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *principal;
27575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct transmit_sa *txsa;
27585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
27595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	principal = ieee802_1x_kay_get_principal_participant(kay);
27605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!principal)
27615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
27625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
27635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(txsa, &principal->txsc->sa_list, struct transmit_sa,
27645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			 list) {
27655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (is_ki_equal(&txsa->pkey->key_identifier, lki)) {
27665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			txsa->in_use = TRUE;
27675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			secy_enable_transmit_sa(kay, txsa);
27685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_cp_set_usingtransmitas(
27695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				principal->kay->cp, TRUE);
27705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_cp_sm_step(principal->kay->cp);
27715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
27725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
27735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
27745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
27755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
27765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
27775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
27785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
27795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_enable_rx_sas -
27805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
27815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtint ieee802_1x_kay_enable_rx_sas(struct ieee802_1x_kay *kay,
27825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				 struct ieee802_1x_mka_ki *lki)
27835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
27845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *principal;
27855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct receive_sa *rxsa;
27865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct receive_sc *rxsc;
27875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
27885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	principal = ieee802_1x_kay_get_principal_participant(kay);
27895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!principal)
27905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
27915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
27925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(rxsc, &principal->rxsc_list, struct receive_sc, list) {
27935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		dl_list_for_each(rxsa, &rxsc->sa_list, struct receive_sa, list)
27945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		{
27955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			if (is_ki_equal(&rxsa->pkey->key_identifier, lki)) {
27965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				rxsa->in_use = TRUE;
27975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				secy_enable_receive_sa(kay, rxsa);
27985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				ieee802_1x_cp_set_usingreceivesas(
27995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					principal->kay->cp, TRUE);
28005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				ieee802_1x_cp_sm_step(principal->kay->cp);
28015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			}
28025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
28035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
28045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
28055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
28065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
28075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
28085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
28095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
28105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_enable_new_info -
28115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
28125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtint ieee802_1x_kay_enable_new_info(struct ieee802_1x_kay *kay)
28135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
28145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *principal;
28155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
28165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	principal = ieee802_1x_kay_get_principal_participant(kay);
28175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!principal)
28185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
28195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
28205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (principal->retry_count < MAX_RETRY_CNT) {
28215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_participant_send_mkpdu(principal);
28225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		principal->retry_count++;
28235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
28245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
28255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
28265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
28275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
28285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
28295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
28305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_cp_conf -
28315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
28325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtint ieee802_1x_kay_cp_conf(struct ieee802_1x_kay *kay,
28335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   struct ieee802_1x_cp_conf *pconf)
28345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
28355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	pconf->protect = kay->macsec_protect;
28365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	pconf->replay_protect = kay->macsec_replay_protect;
28375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	pconf->validate = kay->macsec_validate;
28385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
28395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
28405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
28415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
28425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
28435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
28445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_alloc_cp_sm -
28455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
28465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic struct ieee802_1x_cp_sm *
28475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_alloc_cp_sm(struct ieee802_1x_kay *kay)
28485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
28495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_cp_conf conf;
28505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
28515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memset(&conf, 0, sizeof(conf));
28525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	conf.protect = kay->macsec_protect;
28535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	conf.replay_protect = kay->macsec_replay_protect;
28545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	conf.validate = kay->macsec_validate;
28555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	conf.replay_window = kay->macsec_replay_window;
28565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
28575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return ieee802_1x_cp_sm_init(kay, &conf);
28585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
28595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
28605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
28615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
28625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_mkpdu_sanity_check -
28635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt *     sanity check specified in clause 11.11.2 of IEEE802.1X-2010
28645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
28655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int ieee802_1x_kay_mkpdu_sanity_check(struct ieee802_1x_kay *kay,
28665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					     const u8 *buf, size_t len)
28675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
28685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee8023_hdr *eth_hdr;
28695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_hdr *eapol_hdr;
28705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_hdr *mka_hdr;
28715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_basic_body *body;
28725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t mka_msg_len;
28735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant;
28745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t body_len;
28755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	u8 icv[MAX_ICV_LEN];
28765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	u8 *msg_icv;
28775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
28785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	eth_hdr = (struct ieee8023_hdr *) buf;
28795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	eapol_hdr = (struct ieee802_1x_hdr *) (eth_hdr + 1);
28805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	mka_hdr = (struct ieee802_1x_mka_hdr *) (eapol_hdr + 1);
28815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
28825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* destination address should be not individual address */
28835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (os_memcmp(eth_hdr->dest, pae_group_addr, ETH_ALEN) != 0) {
28845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_MSGDUMP,
28855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   "KaY: ethernet destination address is not PAE group address");
28865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
28875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
28885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
28895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* MKPDU should not less than 32 octets */
28905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	mka_msg_len = be_to_host16(eapol_hdr->length);
28915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (mka_msg_len < 32) {
28925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_MSGDUMP, "KaY: MKPDU is less than 32 octets");
28935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
28945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
28955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* MKPDU should multiple 4 octets */
28965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if ((mka_msg_len % 4) != 0) {
28975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_MSGDUMP,
28985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   "KaY: MKPDU is not multiple of 4 octets");
28995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
29005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
29015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
29025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body = (struct ieee802_1x_mka_basic_body *) mka_hdr;
29035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_mka_dump_basic_body(body);
29045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body_len = get_mka_param_body_len(body);
29055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* EAPOL-MKA body should comprise basic parameter set and ICV */
29065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (mka_msg_len < MKA_HDR_LEN + body_len + DEFAULT_ICV_LEN) {
29075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR,
29085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   "KaY: Received EAPOL-MKA Packet Body Length (%d bytes) is less than the Basic Parameter Set Header Length (%d bytes) + the Basic Parameter Set Body Length (%d bytes) + %d bytes of ICV",
29095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   (int) mka_msg_len, (int) MKA_HDR_LEN,
29105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   (int) body_len, DEFAULT_ICV_LEN);
29115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
29125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
29135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
29145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* CKN should be owned by I */
29155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant = ieee802_1x_kay_get_participant(kay, body->ckn);
29165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!participant) {
29175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_DEBUG, "CKN is not included in my CA");
29185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
29195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
29205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
29215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* algorithm agility check */
29225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (os_memcmp(body->algo_agility, mka_algo_agility,
29235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		      sizeof(body->algo_agility)) != 0) {
29245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR,
29255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   "KaY: peer's algorithm agility not supported for me");
29265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
29275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
29285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
29295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* ICV check */
29305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/*
29315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 * The ICV will comprise the final octets of the packet body, whatever
29325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 * its size, not the fixed length 16 octets, indicated by the EAPOL
29335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 * packet body length.
29345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 */
29355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (mka_alg_tbl[kay->mka_algindex].icv_hash(
29365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		    participant->ick.key,
29375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		    buf, len - mka_alg_tbl[kay->mka_algindex].icv_len, icv)) {
29385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY: omac1_aes_128 failed");
29395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
29405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
29415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	msg_icv = ieee802_1x_mka_decode_icv_body(participant, (u8 *) mka_hdr,
29425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt						 mka_msg_len);
29435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
29445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (msg_icv) {
2945c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt		if (os_memcmp_const(msg_icv, icv,
2946c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt				    mka_alg_tbl[kay->mka_algindex].icv_len) !=
2947c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt		    0) {
29485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			wpa_printf(MSG_ERROR,
29495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				   "KaY: Computed ICV is not equal to Received ICV");
29505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
29515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
29525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	} else {
29535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY: No ICV");
29545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
29555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
29565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
29575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
29585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
29595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
29605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
29615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
29625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_decode_mkpdu -
29635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
29645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int ieee802_1x_kay_decode_mkpdu(struct ieee802_1x_kay *kay,
29655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				       const u8 *buf, size_t len)
29665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
29675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant;
29685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_hdr *hdr;
29695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t body_len;
29705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t left_len;
29715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	int body_type;
29725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	int i;
29735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	const u8 *pos;
29745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	Boolean my_included;
29755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	Boolean handled[256];
29765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
29775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (ieee802_1x_kay_mkpdu_sanity_check(kay, buf, len))
29785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
29795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
29805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* handle basic parameter set */
29815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	pos = buf + sizeof(struct ieee8023_hdr) + sizeof(struct ieee802_1x_hdr);
29825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	left_len = len - sizeof(struct ieee8023_hdr) -
29835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		sizeof(struct ieee802_1x_hdr);
29845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant = ieee802_1x_mka_decode_basic_body(kay, pos, left_len);
29855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!participant)
29865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
29875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
29885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* to skip basic parameter set */
29895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	hdr = (struct ieee802_1x_mka_hdr *) pos;
29905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body_len = get_mka_param_body_len(hdr);
29915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	pos += body_len + MKA_HDR_LEN;
29925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	left_len -= body_len + MKA_HDR_LEN;
29935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
29945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* check i am in the peer's peer list */
29955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	my_included = ieee802_1x_mka_i_in_peerlist(participant, pos, left_len);
29965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (my_included) {
29975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		/* accept the peer as live peer */
29985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (!ieee802_1x_kay_is_in_peer(
29995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			    participant,
30005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			    participant->current_peer_id.mi)) {
30015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			if (!ieee802_1x_kay_create_live_peer(
30025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				    participant,
30035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				    participant->current_peer_id.mi,
30045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				    participant->current_peer_id.mn))
30055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				return -1;
30065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_kay_elect_key_server(participant);
30075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_kay_decide_macsec_use(participant);
30085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
30095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (ieee802_1x_kay_is_in_potential_peer(
30105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			    participant, participant->current_peer_id.mi)) {
30115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_kay_move_live_peer(
30125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				participant, participant->current_peer_id.mi,
30135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				participant->current_peer_id.mn);
30145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_kay_elect_key_server(participant);
30155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_kay_decide_macsec_use(participant);
30165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
30175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
30185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
30195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/*
30205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 * Handle other parameter set than basic parameter set.
30215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 * Each parameter set should be present only once.
30225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 */
30235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	for (i = 0; i < 256; i++)
30245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		handled[i] = FALSE;
30255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
30265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	handled[0] = TRUE;
30275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	while (left_len > MKA_HDR_LEN + DEFAULT_ICV_LEN) {
30285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		hdr = (struct ieee802_1x_mka_hdr *) pos;
30295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body_len = get_mka_param_body_len(hdr);
30305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body_type = get_mka_param_body_type(hdr);
30315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
30325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (body_type == MKA_ICV_INDICATOR)
30335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			return 0;
30345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
30355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (left_len < (MKA_HDR_LEN + body_len + DEFAULT_ICV_LEN)) {
30365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			wpa_printf(MSG_ERROR,
30375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				   "KaY: MKA Peer Packet Body Length (%d bytes) is less than the Parameter Set Header Length (%d bytes) + the Parameter Set Body Length (%d bytes) + %d bytes of ICV",
30385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				   (int) left_len, (int) MKA_HDR_LEN,
30395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				   (int) body_len, DEFAULT_ICV_LEN);
30405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			goto next_para_set;
30415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
30425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
30435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (handled[body_type])
30445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			goto next_para_set;
30455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
30465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		handled[body_type] = TRUE;
30475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (mak_body_handler[body_type].body_rx) {
30485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			mak_body_handler[body_type].body_rx
30495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				(participant, pos, left_len);
30505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		} else {
30515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			wpa_printf(MSG_ERROR,
30525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				   "The type %d not supported in this MKA version %d",
30535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				   body_type, MKA_VERSION_ID);
30545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
30555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
30565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtnext_para_set:
30575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		pos += body_len + MKA_HDR_LEN;
30585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		left_len -= body_len + MKA_HDR_LEN;
30595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
30605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
30615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->active = TRUE;
30625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->retry_count = 0;
30635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->active = TRUE;
30645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
30655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
30665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
30675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
30685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
30695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
30705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic void kay_l2_receive(void *ctx, const u8 *src_addr, const u8 *buf,
30715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   size_t len)
30725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
30735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay *kay = ctx;
30745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee8023_hdr *eth_hdr;
30755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_hdr *eapol_hdr;
30765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
30775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* must contain at least ieee8023_hdr + ieee802_1x_hdr */
30785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (len < sizeof(*eth_hdr) + sizeof(*eapol_hdr)) {
30795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_MSGDUMP, "KaY: EAPOL frame too short (%lu)",
30805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   (unsigned long) len);
30815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return;
30825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
30835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
30845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	eth_hdr = (struct ieee8023_hdr *) buf;
30855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	eapol_hdr = (struct ieee802_1x_hdr *) (eth_hdr + 1);
30865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (len != sizeof(*eth_hdr) + sizeof(*eapol_hdr) +
30875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	    ntohs(eapol_hdr->length)) {
30885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_MSGDUMP, "KAY: EAPOL MPDU is invalid: (%lu-%lu)",
30895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   (unsigned long) len,
30905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   (unsigned long) ntohs(eapol_hdr->length));
30915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return;
30925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
30935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
30945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (eapol_hdr->version < EAPOL_VERSION) {
30955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_MSGDUMP, "KaY: version %d does not support MKA",
30965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   eapol_hdr->version);
30975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return;
30985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
30995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (ntohs(eth_hdr->ethertype) != ETH_P_PAE ||
31005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	    eapol_hdr->type != IEEE802_1X_TYPE_EAPOL_MKA)
31015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return;
31025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
31035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_hexdump(MSG_DEBUG, "RX EAPOL-MKA: ", buf, len);
31045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (dl_list_empty(&kay->participant_list)) {
31055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY: no MKA participant instance");
31065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return;
31075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
31085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
31095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_kay_decode_mkpdu(kay, buf, len);
31105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
31115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
31125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
31135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
31145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_init -
31155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
31165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstruct ieee802_1x_kay *
31175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_init(struct ieee802_1x_kay_ctx *ctx, enum macsec_policy policy,
31185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		    const char *ifname, const u8 *addr)
31195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
31205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay *kay;
31215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
31225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay = os_zalloc(sizeof(*kay));
31235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!kay) {
31245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY-%s: out of memory", __func__);
31255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return NULL;
31265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
31275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
31285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->ctx = ctx;
31295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
31305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->enable = TRUE;
31315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->active = FALSE;
31325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
31335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->authenticated = FALSE;
31345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->secured = FALSE;
31355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->failed = FALSE;
31365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->policy = policy;
31375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
31385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_strlcpy(kay->if_name, ifname, IFNAMSIZ);
31395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(kay->actor_sci.addr, addr, ETH_ALEN);
31405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->actor_sci.port = 0x0001;
31415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->actor_priority = DEFAULT_PRIO_NOT_KEY_SERVER;
31425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
31435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* While actor acts as a key server, shall distribute sakey */
31445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->dist_kn = 1;
31455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->dist_an = 0;
31465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->dist_time = 0;
31475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
31485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->pn_exhaustion = PENDING_PN_EXHAUSTION;
31495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->macsec_csindex = DEFAULT_CS_INDEX;
31505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->mka_algindex = DEFAULT_MKA_ALG_INDEX;
31515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->mka_version = MKA_VERSION_ID;
31525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
31535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(kay->algo_agility, mka_algo_agility,
31545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		  sizeof(kay->algo_agility));
31555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
31565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_init(&kay->participant_list);
31575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
31585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (policy == DO_NOT_SECURE) {
31595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->macsec_capable = MACSEC_CAP_NOT_IMPLEMENTED;
31605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->macsec_desired = FALSE;
31615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->macsec_protect = FALSE;
31625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->macsec_validate = FALSE;
31635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->macsec_replay_protect = FALSE;
31645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->macsec_replay_window = 0;
31655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->macsec_confidentiality = CONFIDENTIALITY_NONE;
31665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	} else {
31675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->macsec_capable = MACSEC_CAP_INTEG_AND_CONF_0_30_50;
31685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->macsec_desired = TRUE;
31695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->macsec_protect = TRUE;
31705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->macsec_validate = TRUE;
31715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->macsec_replay_protect = FALSE;
31725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->macsec_replay_window = 0;
31735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->macsec_confidentiality = CONFIDENTIALITY_OFFSET_0;
31745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
31755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
31765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "KaY: state machine created");
31775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
31785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* Initialize the SecY must be prio to CP, as CP will control SecY */
31795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	secy_init_macsec(kay);
31805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	secy_get_available_transmit_sc(kay, &kay->sc_ch);
31815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
31825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "KaY: secy init macsec done");
31835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
31845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* init CP */
31855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->cp = ieee802_1x_kay_alloc_cp_sm(kay);
31865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (kay->cp == NULL) {
31875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_kay_deinit(kay);
31885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return NULL;
31895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
31905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
31915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (policy == DO_NOT_SECURE) {
31925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_cp_connect_authenticated(kay->cp);
31935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_cp_sm_step(kay->cp);
31945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	} else {
31955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->l2_mka = l2_packet_init(kay->if_name, NULL, ETH_P_PAE,
31965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					     kay_l2_receive, kay, 1);
31975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (kay->l2_mka == NULL) {
31985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			wpa_printf(MSG_WARNING,
31995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				   "KaY: Failed to initialize L2 packet processing for MKA packet");
32005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_kay_deinit(kay);
32015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			return NULL;
32025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
32035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
32045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
32055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return kay;
32065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
32075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
32085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
32095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
32105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_deinit -
32115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
32125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtvoid
32135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_deinit(struct ieee802_1x_kay *kay)
32145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
32155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant;
32165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
32175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!kay)
32185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return;
32195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
32205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "KaY: state machine removed");
32215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
32225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	while (!dl_list_empty(&kay->participant_list)) {
32235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant = dl_list_entry(kay->participant_list.next,
32245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					    struct ieee802_1x_mka_participant,
32255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					    list);
32265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_kay_delete_mka(kay, &participant->ckn);
32275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
32285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
32295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_cp_sm_deinit(kay->cp);
32305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	secy_deinit_macsec(kay);
32315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
32325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (kay->l2_mka) {
32335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		l2_packet_deinit(kay->l2_mka);
32345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->l2_mka = NULL;
32355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
32365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
32375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_free(kay->ctx);
32385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_free(kay);
32395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
32405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
32415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
32425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
32435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_create_mka -
32445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
32455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstruct ieee802_1x_mka_participant *
32465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_create_mka(struct ieee802_1x_kay *kay, struct mka_key_name *ckn,
32475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			  struct mka_key *cak, u32 life,
32485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			  enum mka_created_mode mode, Boolean is_authenticator)
32495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
32505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant;
32515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	unsigned int usecs;
32525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
32535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!kay || !ckn || !cak) {
32545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY: ckn or cak is null");
32555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return NULL;
32565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
32575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
32585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (cak->len != mka_alg_tbl[kay->mka_algindex].cak_len) {
32595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY: CAK length not follow key schema");
32605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return NULL;
32615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
32625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (ckn->len > MAX_CKN_LEN) {
32635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY: CKN is out of range(<=32 bytes)");
32645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return NULL;
32655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
32665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!kay->enable) {
32675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY: Now is at disable state");
32685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return NULL;
32695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
32705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
32715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant = os_zalloc(sizeof(*participant));
32725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!participant) {
32735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY-%s: out of memory", __func__);
32745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return NULL;
32755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
32765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
32775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->ckn.len = ckn->len;
32785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(participant->ckn.name, ckn->name, ckn->len);
32795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->cak.len = cak->len;
32805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(participant->cak.key, cak->key, cak->len);
32815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (life)
32825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->cak_life = life + time(NULL);
32835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
32845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	switch (mode) {
32855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	case EAP_EXCHANGE:
32865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (is_authenticator) {
32875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->is_obliged_key_server = TRUE;
32885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->can_be_key_server = TRUE;
32895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->is_key_server = TRUE;
32905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->principal = TRUE;
32915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
32925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			os_memcpy(&kay->key_server_sci, &kay->actor_sci,
32935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				  sizeof(kay->key_server_sci));
32945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			kay->key_server_priority = kay->actor_priority;
32955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->is_elected = TRUE;
32965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		} else {
32975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->is_obliged_key_server = FALSE;
32985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->can_be_key_server = FALSE;
32995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->is_key_server = FALSE;
33005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->is_elected = TRUE;
33015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
33025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		break;
33035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
33045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	default:
33055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->is_obliged_key_server = FALSE;
33065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->can_be_key_server = TRUE;
33075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->is_key_server = FALSE;
33085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->is_elected = FALSE;
33095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		break;
33105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
33115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
33125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->cached = FALSE;
33135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
33145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->active = FALSE;
33155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->participant = FALSE;
33165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->retain = FALSE;
33175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->activate = DEFAULT;
33185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
33195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (participant->is_key_server)
33205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->principal = TRUE;
33215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
33225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_init(&participant->live_peers);
33235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_init(&participant->potential_peers);
33245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
33255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->retry_count = 0;
33265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->kay = kay;
33275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
33285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_get_random(participant->mi, sizeof(participant->mi));
33295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->mn = 0;
33305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
33315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->lrx = FALSE;
33325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->ltx = FALSE;
33335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->orx = FALSE;
33345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->otx = FALSE;
33355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->to_dist_sak = FALSE;
33365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->to_use_sak = FALSE;
33375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->new_sak = FALSE;
33385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_init(&participant->sak_list);
33395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->new_key = NULL;
33405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_init(&participant->rxsc_list);
33415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->txsc = ieee802_1x_kay_init_transmit_sc(&kay->actor_sci,
33425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt							    kay->sc_ch);
33435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	secy_create_transmit_sc(kay, participant->txsc);
33445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
33455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* to derive KEK from CAK and CKN */
33465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->kek.len = mka_alg_tbl[kay->mka_algindex].kek_len;
33475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (mka_alg_tbl[kay->mka_algindex].kek_trfm(participant->cak.key,
33485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt						    participant->ckn.name,
33495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt						    participant->ckn.len,
33505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt						    participant->kek.key)) {
33515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY: Derived KEK failed");
33525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		goto fail;
33535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
33545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_hexdump_key(MSG_DEBUG, "KaY: Derived KEK",
33555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->kek.key, participant->kek.len);
33565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
33575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* to derive ICK from CAK and CKN */
33585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->ick.len = mka_alg_tbl[kay->mka_algindex].ick_len;
33595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (mka_alg_tbl[kay->mka_algindex].ick_trfm(participant->cak.key,
33605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt						    participant->ckn.name,
33615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt						    participant->ckn.len,
33625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt						    participant->ick.key)) {
33635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY: Derived ICK failed");
33645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		goto fail;
33655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
33665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_hexdump_key(MSG_DEBUG, "KaY: Derived ICK",
33675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->ick.key, participant->ick.len);
33685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
33695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_add(&kay->participant_list, &participant->list);
33705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_hexdump(MSG_DEBUG, "KaY: Participant created:",
33715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		    ckn->name, ckn->len);
33725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
33735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	usecs = os_random() % (MKA_HELLO_TIME * 1000);
33745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	eloop_register_timeout(0, usecs, ieee802_1x_participant_timer,
33755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			       participant, NULL);
33765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->mka_life = MKA_LIFE_TIME / 1000 + time(NULL) +
33775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		usecs / 1000000;
33785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
33795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return participant;
33805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
33815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtfail:
33825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_free(participant);
33835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return NULL;
33845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
33855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
33865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
33875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
33885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_delete_mka -
33895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
33905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtvoid
33915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_delete_mka(struct ieee802_1x_kay *kay, struct mka_key_name *ckn)
33925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
33935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant;
33945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay_peer *peer;
33955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct data_key *sak;
33965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct receive_sc *rxsc;
33975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
33985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!kay || !ckn)
33995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return;
34005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
34015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "KaY: participant removed");
34025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
34035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* get the participant */
34045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant = ieee802_1x_kay_get_participant(kay, ckn->name);
34055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!participant) {
34065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_hexdump(MSG_DEBUG, "KaY: participant is not found",
34075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			    ckn->name, ckn->len);
34085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return;
34095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
34105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
34115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_del(&participant->list);
34125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
34135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* remove live peer */
34145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	while (!dl_list_empty(&participant->live_peers)) {
34155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		peer = dl_list_entry(participant->live_peers.next,
34165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				     struct ieee802_1x_kay_peer, list);
34175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		dl_list_del(&peer->list);
34185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(peer);
34195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
34205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
34215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* remove potential peer */
34225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	while (!dl_list_empty(&participant->potential_peers)) {
34235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		peer = dl_list_entry(participant->potential_peers.next,
34245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				     struct ieee802_1x_kay_peer, list);
34255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		dl_list_del(&peer->list);
34265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(peer);
34275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
34285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
34295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* remove sak */
34305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	while (!dl_list_empty(&participant->sak_list)) {
34315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		sak = dl_list_entry(participant->sak_list.next,
34325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				    struct data_key, list);
34335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		dl_list_del(&sak->list);
34345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(sak->key);
34355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(sak);
34365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
34375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	while (!dl_list_empty(&participant->rxsc_list)) {
34385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		rxsc = dl_list_entry(participant->rxsc_list.next,
34395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				     struct receive_sc, list);
34405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		secy_delete_receive_sc(kay, rxsc);
34415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_kay_deinit_receive_sc(participant, rxsc);
34425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
34435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	secy_delete_transmit_sc(kay, participant->txsc);
34445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_kay_deinit_transmit_sc(participant, participant->txsc);
34455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
34465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memset(&participant->cak, 0, sizeof(participant->cak));
34475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memset(&participant->kek, 0, sizeof(participant->kek));
34485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memset(&participant->ick, 0, sizeof(participant->ick));
34495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_free(participant);
34505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
34515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
34525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
34535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
34545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_mka_participate -
34555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
34565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtvoid ieee802_1x_kay_mka_participate(struct ieee802_1x_kay *kay,
34575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				    struct mka_key_name *ckn,
34585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				    Boolean status)
34595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
34605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant;
34615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
34625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!kay || !ckn)
34635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return;
34645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
34655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant = ieee802_1x_kay_get_participant(kay, ckn->name);
34665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!participant)
34675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return;
34685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
34695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->active = status;
34705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
34715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
34725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
34735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
34745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_new_sak -
34755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
34765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtint
34775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_new_sak(struct ieee802_1x_kay *kay)
34785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
34795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant;
34805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
34815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!kay)
34825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
34835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
34845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant = ieee802_1x_kay_get_principal_participant(kay);
34855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!participant)
34865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
34875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
34885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->new_sak = TRUE;
34895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "KaY: new SAK signal");
34905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
34915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
34925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
34935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
34945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
34955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
34965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_change_cipher_suite -
34975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
34985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtint
34995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_change_cipher_suite(struct ieee802_1x_kay *kay, int cs_index)
35005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
35015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant;
35025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
35035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!kay)
35045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
35055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
35065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if ((unsigned int) cs_index >= CS_TABLE_SIZE) {
35075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR,
35085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   "KaY: Configured cipher suite index is out of range");
35095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
35105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
35115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (kay->macsec_csindex == cs_index)
35125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -2;
35135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
35145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (cs_index == 0)
35155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->macsec_desired = FALSE;
35165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
35175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->macsec_csindex = cs_index;
35185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->macsec_capable = cipher_suite_tbl[kay->macsec_csindex].capable;
35195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
35205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant = ieee802_1x_kay_get_principal_participant(kay);
35215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (participant) {
35225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_INFO, "KaY: Cipher Suite changed");
35235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->new_sak = TRUE;
35245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
35255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
35265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
35275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
3528