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) {
732fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt		if (os_get_random(participant->mi, sizeof(participant->mi)) < 0)
733fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt			return NULL;
7345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->mn = 0;
7355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
7365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
7375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(participant->current_peer_id.mi, body->actor_mi, MI_LEN);
7385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->current_peer_id.mn =  be_to_host32(body->actor_mn);
7395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(participant->current_peer_sci.addr, body->actor_sci.addr,
7405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		  sizeof(participant->current_peer_sci.addr));
7415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->current_peer_sci.port = be_to_host16(body->actor_sci.port);
7425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
7435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* handler peer */
7445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	peer = ieee802_1x_kay_get_peer(participant, body->actor_mi);
7455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!peer) {
7465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		/* Check duplicated SCI */
7475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		/* TODO: What policy should be applied to detect duplicated SCI
7485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		 * is active attacker or a valid peer whose MI is be changed?
7495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		 */
7505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		peer = ieee802_1x_kay_get_peer_sci(participant,
7515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt						   &body->actor_sci);
7525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (peer) {
7535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			wpa_printf(MSG_WARNING,
7545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				   "KaY: duplicated SCI detected, Maybe active attacker");
7555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			dl_list_del(&peer->list);
7565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			os_free(peer);
7575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
7585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
7595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		peer = ieee802_1x_kay_create_potential_peer(
7605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant, body->actor_mi,
7615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			be_to_host32(body->actor_mn));
7625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (!peer)
7635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			return NULL;
7645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
7655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		peer->macsec_desired = body->macsec_desired;
7665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		peer->macsec_capbility = body->macsec_capbility;
7675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		peer->is_key_server = (Boolean) body->key_server;
7685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		peer->key_server_priority = body->priority;
7695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	} else if (peer->mn < be_to_host32(body->actor_mn)) {
7705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		peer->mn = be_to_host32(body->actor_mn);
7715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		peer->expire = time(NULL) + MKA_LIFE_TIME / 1000;
7725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		peer->macsec_desired = body->macsec_desired;
7735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		peer->macsec_capbility = body->macsec_capbility;
7745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		peer->is_key_server = (Boolean) body->key_server;
7755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		peer->key_server_priority = body->priority;
7765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	} else {
7775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_WARNING, "KaY: The peer MN have received");
7785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return NULL;
7795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
7805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
7815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return participant;
7825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
7835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
7845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
7855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
7865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_live_peer_body_present
7875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
7885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic Boolean
7895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_live_peer_body_present(
7905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant)
7915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
7925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return !dl_list_empty(&participant->live_peers);
7935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
7945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
7955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
7965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
7975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_get_live_peer_length
7985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
7995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
8005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_get_live_peer_length(
8015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant)
8025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
8035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	int len = MKA_HDR_LEN;
8045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay_peer *peer;
8055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
8065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(peer, &participant->live_peers,
8075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			 struct ieee802_1x_kay_peer, list)
8085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		len += sizeof(struct ieee802_1x_mka_peer_id);
8095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
8105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return (len + 0x3) & ~0x3;
8115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
8125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
8135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
8145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
8155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_encode_live_peer_body -
8165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
8175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
8185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_encode_live_peer_body(
8195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant,
8205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct wpabuf *buf)
8215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
8225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_peer_body *body;
8235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay_peer *peer;
8245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	unsigned int length;
8255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_peer_id *body_peer;
8265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
8275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	length = ieee802_1x_mka_get_live_peer_length(participant);
8285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body = wpabuf_put(buf, sizeof(struct ieee802_1x_mka_peer_body));
8295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
8305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body->type = MKA_LIVE_PEER_LIST;
8315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	set_mka_param_body_len(body, length - MKA_HDR_LEN);
8325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
8335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(peer, &participant->live_peers,
8345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			 struct ieee802_1x_kay_peer, list) {
8355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body_peer = wpabuf_put(buf,
8365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				       sizeof(struct ieee802_1x_mka_peer_id));
8375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_memcpy(body_peer->mi, peer->mi, MI_LEN);
8385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body_peer->mn = host_to_be32(peer->mn);
8395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body_peer++;
8405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
8415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
8425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_mka_dump_peer_body(body);
8435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
8445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
8455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
8465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
8475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_potential_peer_body_present
8485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
8495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic Boolean
8505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_potential_peer_body_present(
8515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant)
8525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
8535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return !dl_list_empty(&participant->potential_peers);
8545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
8555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
8565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
8575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
8585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_get_potential_peer_length
8595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
8605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
8615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_get_potential_peer_length(
8625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant)
8635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
8645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	int len = MKA_HDR_LEN;
8655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay_peer *peer;
8665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
8675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(peer, &participant->potential_peers,
8685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			 struct ieee802_1x_kay_peer, list)
8695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		len += sizeof(struct ieee802_1x_mka_peer_id);
8705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
8715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return (len + 0x3) & ~0x3;
8725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
8735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
8745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
8755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
8765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_encode_potential_peer_body -
8775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
8785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
8795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_encode_potential_peer_body(
8805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant,
8815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct wpabuf *buf)
8825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
8835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_peer_body *body;
8845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay_peer *peer;
8855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	unsigned int length;
8865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_peer_id *body_peer;
8875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
8885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	length = ieee802_1x_mka_get_potential_peer_length(participant);
8895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body = wpabuf_put(buf, sizeof(struct ieee802_1x_mka_peer_body));
8905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
8915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body->type = MKA_POTENTIAL_PEER_LIST;
8925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	set_mka_param_body_len(body, length - MKA_HDR_LEN);
8935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
8945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(peer, &participant->potential_peers,
8955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			 struct ieee802_1x_kay_peer, list) {
8965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body_peer = wpabuf_put(buf,
8975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				       sizeof(struct ieee802_1x_mka_peer_id));
8985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_memcpy(body_peer->mi, peer->mi, MI_LEN);
8995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body_peer->mn = host_to_be32(peer->mn);
9005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body_peer++;
9015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
9025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
9035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_mka_dump_peer_body(body);
9045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
9055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
9065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
9075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
9085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
9095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_i_in_peerlist -
9105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
9115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic Boolean
9125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_i_in_peerlist(struct ieee802_1x_mka_participant *participant,
9135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			     const u8 *mka_msg, size_t msg_len)
9145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
9155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	Boolean included = FALSE;
9165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_hdr *hdr;
9175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t body_len;
9185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t left_len;
9195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	int body_type;
9205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	u32 peer_mn;
9215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	const u8 *peer_mi;
9225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	const u8 *pos;
9235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t i;
9245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
9255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	pos = mka_msg;
9265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	left_len = msg_len;
9275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	while (left_len > (MKA_HDR_LEN + DEFAULT_ICV_LEN)) {
9285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		hdr = (struct ieee802_1x_mka_hdr *) pos;
9295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body_len = get_mka_param_body_len(hdr);
9305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body_type = get_mka_param_body_type(hdr);
9315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
9325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (body_type != MKA_LIVE_PEER_LIST &&
9335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		    body_type != MKA_POTENTIAL_PEER_LIST)
9345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			goto SKIP_PEER;
9355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
9365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_dump_peer_body(
9375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			(struct ieee802_1x_mka_peer_body *)pos);
9385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
9395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (left_len < (MKA_HDR_LEN + body_len + DEFAULT_ICV_LEN)) {
9405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			wpa_printf(MSG_ERROR,
9415a1480c7c46c4236d93bfd303dde32062bee04acDmitry 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",
9425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				   (int) left_len, (int) MKA_HDR_LEN,
9435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				   (int) body_len, DEFAULT_ICV_LEN);
9445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			goto SKIP_PEER;
9455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
9465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
9475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if ((body_len % 16) != 0) {
9485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			wpa_printf(MSG_ERROR,
9495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				   "KaY: MKA Peer Packet Body Length (%d bytes) should multiple of 16 octets",
9505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				   (int) body_len);
9515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			goto SKIP_PEER;
9525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
9535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
9545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		for (i = 0; i < body_len; i += MI_LEN + sizeof(peer_mn)) {
9555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			peer_mi = MKA_HDR_LEN + pos + i;
9565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			os_memcpy(&peer_mn, peer_mi + MI_LEN, sizeof(peer_mn));
9575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			peer_mn = be_to_host32(peer_mn);
9585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			if (os_memcmp(peer_mi, participant->mi, MI_LEN) == 0 &&
9595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			    peer_mn == participant->mn) {
9605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				included = TRUE;
9615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				break;
9625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			}
9635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
9645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
9655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (included)
9665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			return TRUE;
9675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
9685a1480c7c46c4236d93bfd303dde32062bee04acDmitry ShmidtSKIP_PEER:
9695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		left_len -= body_len + MKA_HDR_LEN;
9705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		pos += body_len + MKA_HDR_LEN;
9715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
9725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
9735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return FALSE;
9745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
9755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
9765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
9775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
9785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_decode_live_peer_body -
9795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
9805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int ieee802_1x_mka_decode_live_peer_body(
9815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant,
9825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	const u8 *peer_msg, size_t msg_len)
9835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
9845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	const struct ieee802_1x_mka_hdr *hdr;
9855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay_peer *peer;
9865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t body_len;
9875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	u32 peer_mn;
9885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	const u8 *peer_mi;
9895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t i;
9905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	Boolean is_included;
9915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
9925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	is_included = ieee802_1x_kay_is_in_live_peer(
9935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant, participant->current_peer_id.mi);
9945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
9955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	hdr = (const struct ieee802_1x_mka_hdr *) peer_msg;
9965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body_len = get_mka_param_body_len(hdr);
9975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
9985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	for (i = 0; i < body_len; i += MI_LEN + sizeof(peer_mn)) {
9995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		peer_mi = MKA_HDR_LEN + peer_msg + i;
10005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_memcpy(&peer_mn, peer_mi + MI_LEN, sizeof(peer_mn));
10015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		peer_mn = be_to_host32(peer_mn);
10025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
10035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		/* it is myself */
10045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (os_memcmp(peer_mi, participant->mi, MI_LEN) == 0) {
10055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			/* My message id is used by other participant */
10065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			if (peer_mn > participant->mn) {
1007fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt				if (os_get_random(participant->mi,
1008fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt						  sizeof(participant->mi)) < 0)
1009fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt					wpa_printf(MSG_DEBUG,
1010fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt						   "KaY: Could not update mi");
10115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				participant->mn = 0;
10125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			}
10135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			continue;
10145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
10155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (!is_included)
10165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			continue;
10175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
10185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		peer = ieee802_1x_kay_get_peer(participant, peer_mi);
10195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (NULL != peer) {
10205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			peer->mn = peer_mn;
10215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			peer->expire = time(NULL) + MKA_LIFE_TIME / 1000;
10225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		} else {
10235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			if (!ieee802_1x_kay_create_potential_peer(
10245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				participant, peer_mi, peer_mn)) {
10255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				return -1;
10265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			}
10275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
10285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
10295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
10305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
10315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
10325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
10335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
10345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
10355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_decode_potential_peer_body -
10365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
10375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
10385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_decode_potential_peer_body(
10395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant,
10405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	const u8 *peer_msg, size_t msg_len)
10415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
10425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_hdr *hdr;
10435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t body_len;
10445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	u32 peer_mn;
10455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	const u8 *peer_mi;
10465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t i;
10475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
10485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	hdr = (struct ieee802_1x_mka_hdr *) peer_msg;
10495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body_len = get_mka_param_body_len(hdr);
10505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
10515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	for (i = 0; i < body_len; i += MI_LEN + sizeof(peer_mn)) {
10525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		peer_mi = MKA_HDR_LEN + peer_msg + i;
10535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_memcpy(&peer_mn, peer_mi + MI_LEN, sizeof(peer_mn));
10545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		peer_mn = be_to_host32(peer_mn);
10555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
10565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		/* it is myself */
10575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (os_memcmp(peer_mi, participant->mi, MI_LEN) == 0) {
10585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			/* My message id is used by other participant */
10595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			if (peer_mn > participant->mn) {
1060fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt				if (os_get_random(participant->mi,
1061fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt						  sizeof(participant->mi)) < 0)
1062fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt					wpa_printf(MSG_DEBUG,
1063fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt						   "KaY: Could not update mi");
10645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				participant->mn = 0;
10655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			}
10665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			continue;
10675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
10685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
10695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
10705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
10715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
10725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
10735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
10745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
10755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_sak_use_body_present
10765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
10775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic Boolean
10785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_sak_use_body_present(
10795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant)
10805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
10815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (participant->to_use_sak)
10825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return TRUE;
10835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	else
10845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return FALSE;
10855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
10865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
10875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
10885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
10895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_get_sak_use_length
10905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
10915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
10925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_get_sak_use_length(
10935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant)
10945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
10955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	int length = MKA_HDR_LEN;
10965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
10975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (participant->kay->macsec_desired && participant->advised_desired)
10985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		length = sizeof(struct ieee802_1x_mka_sak_use_body);
10995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	else
11005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		length = MKA_HDR_LEN;
11015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
11025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	length = (length + 0x3) & ~0x3;
11035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
11045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return length;
11055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
11065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
11075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
11085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
11095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt *
11105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
11115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic u32
11125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_get_lpn(struct ieee802_1x_mka_participant *principal,
11135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		       struct ieee802_1x_mka_ki *ki)
11145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
11155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct receive_sa *rxsa;
11165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct receive_sc *rxsc;
11175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	u32 lpn = 0;
11185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
11195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(rxsc, &principal->rxsc_list, struct receive_sc, list) {
11205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		dl_list_for_each(rxsa, &rxsc->sa_list, struct receive_sa, list)
11215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		{
11225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			if (is_ki_equal(&rxsa->pkey->key_identifier, ki)) {
11235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				secy_get_receive_lowest_pn(principal->kay,
11245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt							   rxsa);
11255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
11265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				lpn = lpn > rxsa->lowest_pn ?
11275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					lpn : rxsa->lowest_pn;
11285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				break;
11295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			}
11305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
11315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
11325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
11335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (lpn == 0)
11345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		lpn = 1;
11355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
11365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return lpn;
11375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
11385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
11395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
11405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
11415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_encode_sak_use_body -
11425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
11435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
11445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_encode_sak_use_body(
11455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant,
11465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct wpabuf *buf)
11475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
11485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_sak_use_body *body;
11495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	unsigned int length;
11505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	u32 pn = 1;
11515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
11525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	length = ieee802_1x_mka_get_sak_use_length(participant);
11535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body = wpabuf_put(buf, sizeof(struct ieee802_1x_mka_sak_use_body));
11545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
11555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body->type = MKA_SAK_USE;
11565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	set_mka_param_body_len(body, length - MKA_HDR_LEN);
11575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
11585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (length == MKA_HDR_LEN) {
11595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body->ptx = TRUE;
11605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body->prx = TRUE;
11615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body->lan = 0;
11625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body->lrx = FALSE;
11635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body->ltx = FALSE;
11645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body->delay_protect = FALSE;
11655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return 0;
11665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
11675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
11685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* data protect, lowest accept packet number */
11695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body->delay_protect = participant->kay->macsec_replay_protect;
11705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	pn = ieee802_1x_mka_get_lpn(participant, &participant->lki);
11715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (pn > participant->kay->pn_exhaustion) {
11725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_WARNING, "KaY: My LPN exhaustion");
11735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (participant->is_key_server)
11745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->new_sak = TRUE;
11755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
11765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
11775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body->llpn = host_to_be32(pn);
11785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	pn = ieee802_1x_mka_get_lpn(participant, &participant->oki);
11795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body->olpn = host_to_be32(pn);
11805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
11815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* plain tx, plain rx */
11825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (participant->kay->macsec_protect)
11835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body->ptx = FALSE;
11845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	else
11855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body->ptx = TRUE;
11865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
11875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (participant->kay->macsec_validate == Strict)
11885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body->prx = FALSE;
11895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	else
11905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body->prx = TRUE;
11915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
11925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* latest key: rx, tx, key server member identifier key number */
11935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body->lan = participant->lan;
11945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(body->lsrv_mi, participant->lki.mi,
11955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		  sizeof(body->lsrv_mi));
11965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body->lkn = host_to_be32(participant->lki.kn);
11975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body->lrx = participant->lrx;
11985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body->ltx = participant->ltx;
11995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
12005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* old key: rx, tx, key server member identifier key number */
12015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body->oan = participant->oan;
12025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (participant->oki.kn != participant->lki.kn &&
12035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	    participant->oki.kn != 0) {
12045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body->otx = TRUE;
12055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body->orx = TRUE;
12065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_memcpy(body->osrv_mi, participant->oki.mi,
12075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			  sizeof(body->osrv_mi));
12085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body->okn = host_to_be32(participant->oki.kn);
12095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	} else {
12105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body->otx = FALSE;
12115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body->orx = FALSE;
12125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
12135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
12145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* set CP's variable */
12155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (body->ltx) {
12165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (!participant->kay->tx_enable)
12175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->kay->tx_enable = TRUE;
12185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
12195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (!participant->kay->port_enable)
12205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->kay->port_enable = TRUE;
12215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
12225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (body->lrx) {
12235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (!participant->kay->rx_enable)
12245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->kay->rx_enable = TRUE;
12255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
12265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
12275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_mka_dump_sak_use_body(body);
12285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
12295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
12305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
12315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
12325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
12335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_decode_sak_use_body -
12345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
12355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
12365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_decode_sak_use_body(
12375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant,
12385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	const u8 *mka_msg, size_t msg_len)
12395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
12405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_hdr *hdr;
12415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_sak_use_body *body;
12425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay_peer *peer;
12435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct transmit_sa *txsa;
12445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct data_key *sa_key = NULL;
12455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t body_len;
12465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_ki ki;
12475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	u32 lpn;
12485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	Boolean all_receiving;
12495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	Boolean founded;
12505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
12515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!participant->principal) {
12525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_WARNING, "KaY: Participant is not principal");
12535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
12545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
12555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	peer = ieee802_1x_kay_get_live_peer(participant,
12565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					    participant->current_peer_id.mi);
12575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!peer) {
12585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_WARNING, "KaY: the peer is not my live peer");
12595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
12605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
12615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
12625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	hdr = (struct ieee802_1x_mka_hdr *) mka_msg;
12635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body_len = get_mka_param_body_len(hdr);
12645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body = (struct ieee802_1x_mka_sak_use_body *) mka_msg;
12655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_mka_dump_sak_use_body(body);
12665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
12675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if ((body_len != 0) && (body_len < 40)) {
12685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR,
12695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   "KaY: MKA Use SAK Packet Body Length (%d bytes) should be 0, 40, or more octets",
12705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   (int) body_len);
12715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
12725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
12735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
12745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* TODO: what action should I take when peer does not support MACsec */
12755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (body_len == 0) {
12765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_WARNING, "KaY: Peer does not support MACsec");
12775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return 0;
12785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
12795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
12805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* TODO: when the plain tx or rx of peer is true, should I change
12815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 * the attribute of controlled port
12825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 */
12835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (body->prx)
12845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_WARNING, "KaY: peer's plain rx are TRUE");
12855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
12865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (body->ptx)
12875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_WARNING, "KaY: peer's plain tx are TRUE");
12885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
12895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* check latest key is valid */
12905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (body->ltx || body->lrx) {
12915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		founded = FALSE;
12925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_memcpy(ki.mi, body->lsrv_mi, sizeof(ki.mi));
12935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ki.kn = ntohl(body->lkn);
12945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		dl_list_for_each(sa_key, &participant->sak_list,
12955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				 struct data_key, list) {
12965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			if (is_ki_equal(&sa_key->key_identifier, &ki)) {
12975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				founded = TRUE;
12985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				break;
12995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			}
13005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
13015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (!founded) {
13025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			wpa_printf(MSG_WARNING, "KaY: Latest key is invalid");
13035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			return -1;
13045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
13055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (os_memcmp(participant->lki.mi, body->lsrv_mi,
13065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			      sizeof(participant->lki.mi)) == 0 &&
13075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		    ntohl(body->lkn) == participant->lki.kn &&
13085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		    body->lan == participant->lan) {
13095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			peer->sak_used = TRUE;
13105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
13115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (body->ltx && peer->is_key_server) {
13125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_cp_set_servertransmitting(
13135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				participant->kay->cp, TRUE);
13145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_cp_sm_step(participant->kay->cp);
13155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
13165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
13175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
13185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* check old key is valid */
13195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (body->otx || body->orx) {
13205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (os_memcmp(participant->oki.mi, body->osrv_mi,
13215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			      sizeof(participant->oki.mi)) != 0 ||
13225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		    ntohl(body->okn) != participant->oki.kn ||
13235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		    body->oan != participant->oan) {
13245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			wpa_printf(MSG_WARNING, "KaY: Old key is invalid");
13255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			return -1;
13265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
13275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
13285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
13295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* TODO: how to set the MACsec hardware when delay_protect is true */
13305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (body->delay_protect && (!ntohl(body->llpn) || !ntohl(body->olpn))) {
13315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_WARNING,
13325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   "KaY: Lowest packet number should greater than 0 when delay_protect is TRUE");
13335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
13345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
13355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
13365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* check all live peer have used the sak for receiving sa */
13375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	all_receiving = TRUE;
13385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(peer, &participant->live_peers,
13395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			 struct ieee802_1x_kay_peer, list) {
13405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (!peer->sak_used) {
13415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			all_receiving = FALSE;
13425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			break;
13435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
13445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
13455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (all_receiving) {
13465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->to_dist_sak = FALSE;
13475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_cp_set_allreceiving(participant->kay->cp, TRUE);
13485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_cp_sm_step(participant->kay->cp);
13495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
13505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
13515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* if i'm key server, and detects peer member pn exhaustion, rekey.*/
13525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	lpn = ntohl(body->llpn);
13535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (lpn > participant->kay->pn_exhaustion) {
13545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (participant->is_key_server) {
13555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->new_sak = TRUE;
13565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			wpa_printf(MSG_WARNING, "KaY: Peer LPN exhaustion");
13575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
13585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
13595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
13605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	founded = FALSE;
13615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(txsa, &participant->txsc->sa_list,
13625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			 struct transmit_sa, list) {
13635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (sa_key != NULL && txsa->pkey == sa_key) {
13645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			founded = TRUE;
13655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			break;
13665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
13675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
13685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!founded) {
13695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_WARNING, "KaY: Can't find txsa");
13705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
13715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
13725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
13735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* FIXME: Secy creates txsa with default npn. If MKA detected Latest Key
13745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 * npn is larger than txsa's npn, set it to txsa.
13755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 */
13765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	secy_get_transmit_next_pn(participant->kay, txsa);
13775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (lpn > txsa->next_pn) {
13785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		secy_set_transmit_next_pn(participant->kay, txsa);
13795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_INFO, "KaY: update lpn =0x%x", lpn);
13805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
13815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
13825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
13835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
13845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
13855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
13865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
13875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_dist_sak_body_present
13885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
13895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic Boolean
13905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_dist_sak_body_present(
13915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant)
13925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
13935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!participant->to_dist_sak || !participant->new_key)
13945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return FALSE;
13955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
13965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return TRUE;
13975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
13985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
13995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
14005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
14015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_get_dist_sak_length
14025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
14035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
14045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_get_dist_sak_length(
14055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant)
14065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
14075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	int length;
14085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	int cs_index = participant->kay->macsec_csindex;
14095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
14105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (participant->advised_desired) {
14115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		length = sizeof(struct ieee802_1x_mka_dist_sak_body);
14125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (cs_index != DEFAULT_CS_INDEX)
14135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			length += CS_ID_LEN;
14145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
14155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		length += cipher_suite_tbl[cs_index].sak_len + 8;
14165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	} else {
14175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		length = MKA_HDR_LEN;
14185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
14195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	length = (length + 0x3) & ~0x3;
14205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
14215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return length;
14225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
14235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
14245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
14255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
14265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_encode_dist_sak_body -
14275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
14285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
14295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_encode_dist_sak_body(
14305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant,
14315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct wpabuf *buf)
14325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
14335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_dist_sak_body *body;
14345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct data_key *sak;
14355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	unsigned int length;
14365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	int cs_index;
14375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	int sak_pos;
14385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
14395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	length = ieee802_1x_mka_get_dist_sak_length(participant);
14405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body = wpabuf_put(buf, length);
14415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body->type = MKA_DISTRIBUTED_SAK;
14425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	set_mka_param_body_len(body, length - MKA_HDR_LEN);
14435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (length == MKA_HDR_LEN) {
14445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body->confid_offset = 0;
14455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body->dan = 0;
14465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return 0;
14475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
14485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
14495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	sak = participant->new_key;
14505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body->confid_offset = sak->confidentiality_offset;
14515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body->dan = sak->an;
14525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body->kn = host_to_be32(sak->key_identifier.kn);
14535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	cs_index = participant->kay->macsec_csindex;
14545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	sak_pos = 0;
14555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (cs_index != DEFAULT_CS_INDEX) {
14565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_memcpy(body->sak, cipher_suite_tbl[cs_index].id, CS_ID_LEN);
14575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		sak_pos = CS_ID_LEN;
14585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
14599ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt	if (aes_wrap(participant->kek.key, 16,
14605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		     cipher_suite_tbl[cs_index].sak_len / 8,
14615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		     sak->key, body->sak + sak_pos)) {
14625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY: AES wrap failed");
14635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
14645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
14655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
14665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_mka_dump_dist_sak_body(body);
14675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
14685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
14695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
14705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
14715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
14725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
14735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_init_data_key -
14745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
14755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic struct data_key *
14765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_init_data_key(const struct key_conf *conf)
14775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
14785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct data_key *pkey;
14795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
14805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!conf)
14815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return NULL;
14825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
14835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	pkey = os_zalloc(sizeof(*pkey));
14845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (pkey == NULL) {
14855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "%s: out of memory", __func__);
14865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return NULL;
14875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
14885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
14895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	pkey->key = os_zalloc(conf->key_len);
14905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (pkey->key == NULL) {
14915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "%s: out of memory", __func__);
14925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(pkey);
14935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return NULL;
14945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
14955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
14965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(pkey->key, conf->key, conf->key_len);
14975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(&pkey->key_identifier, &conf->ki,
14985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		  sizeof(pkey->key_identifier));
14995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	pkey->confidentiality_offset = conf->offset;
15005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	pkey->an = conf->an;
15015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	pkey->transmits = conf->tx;
15025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	pkey->receives = conf->rx;
15035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_get_time(&pkey->created_time);
15045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
15055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	pkey->user = 1;
15065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
15075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return pkey;
15085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
15095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
15105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
15115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
15125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_decode_dist_sak_body -
15135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
15145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
15155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_decode_dist_sak_body(
15165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant,
15175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	const u8 *mka_msg, size_t msg_len)
15185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
15195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_hdr *hdr;
15205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_dist_sak_body *body;
15215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay_peer *peer;
15225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct macsec_ciphersuite *cs;
15235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t body_len;
15245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct key_conf *conf;
15255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct data_key *sa_key = NULL;
15265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_ki sak_ki;
15275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	int sak_len;
15285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	u8 *wrap_sak;
15295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	u8 *unwrap_sak;
15305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
15315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	hdr = (struct ieee802_1x_mka_hdr *) mka_msg;
15325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body_len = get_mka_param_body_len(hdr);
15335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if ((body_len != 0) && (body_len != 28) && (body_len < 36)) {
15345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR,
15355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   "KaY: MKA Use SAK Packet Body Length (%d bytes) should be 0, 28, 36, or more octets",
15365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   (int) body_len);
15375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
15385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
15395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
15405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!participant->principal) {
15415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR,
15425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   "KaY: I can't accept the distributed SAK as I am not principal");
15435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
15445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
15455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (participant->is_key_server) {
15465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR,
15475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   "KaY: I can't accept the distributed SAK as myself is key server ");
15485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
15495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
15505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!participant->kay->macsec_desired ||
15515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	    participant->kay->macsec_capable == MACSEC_CAP_NOT_IMPLEMENTED) {
15525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR,
15535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   "KaY: I am not MACsec-desired or without MACsec capable");
15545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
15555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
15565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
15575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	peer = ieee802_1x_kay_get_live_peer(participant,
15585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					    participant->current_peer_id.mi);
15595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!peer) {
15605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR,
15615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   "KaY: The key server is not in my live peers list");
15625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
15635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
15645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (os_memcmp(&participant->kay->key_server_sci,
15655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		      &peer->sci, sizeof(struct ieee802_1x_mka_sci)) != 0) {
15665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY: The key server is not elected");
15675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
15685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
15695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (body_len == 0) {
15705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->kay->authenticated = TRUE;
15715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->kay->secured = FALSE;
15725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->kay->failed = FALSE;
15735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->advised_desired = FALSE;
15745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_cp_connect_authenticated(participant->kay->cp);
15755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_cp_sm_step(participant->kay->cp);
15765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_WARNING, "KaY:The Key server advise no MACsec");
15775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->to_use_sak = TRUE;
15785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return 0;
15795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
15805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->advised_desired = TRUE;
15815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->kay->authenticated = FALSE;
15825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->kay->secured = TRUE;
15835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->kay->failed = FALSE;
15845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_cp_connect_secure(participant->kay->cp);
15855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_cp_sm_step(participant->kay->cp);
15865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
15875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body = (struct ieee802_1x_mka_dist_sak_body *)mka_msg;
15885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_mka_dump_dist_sak_body(body);
15895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(sa_key, &participant->sak_list, struct data_key, list)
15905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	{
15915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (os_memcmp(sa_key->key_identifier.mi,
15925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			      participant->current_peer_id.mi, MI_LEN) == 0 &&
15935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		    sa_key->key_identifier.kn == be_to_host32(body->kn)) {
15945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			wpa_printf(MSG_WARNING, "KaY:The Key has installed");
15955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			return 0;
15965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
15975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
15985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (body_len == 28) {
15995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		sak_len = DEFAULT_SA_KEY_LEN;
16005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wrap_sak =  body->sak;
16015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->kay->macsec_csindex = DEFAULT_CS_INDEX;
16025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	} else {
16035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		cs = ieee802_1x_kay_get_cipher_suite(participant, body->sak);
16045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (!cs) {
16055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			wpa_printf(MSG_ERROR,
16065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				   "KaY: I can't support the Cipher Suite advised by key server");
16075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			return -1;
16085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
16095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		sak_len = cs->sak_len;
16105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wrap_sak = body->sak + CS_ID_LEN;
16115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->kay->macsec_csindex = cs->index;
16125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
16135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
16145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	unwrap_sak = os_zalloc(sak_len);
16155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!unwrap_sak) {
16165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY-%s: Out of memory", __func__);
16175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
16185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
16199ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt	if (aes_unwrap(participant->kek.key, 16, sak_len >> 3, wrap_sak,
16205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		       unwrap_sak)) {
16215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY: AES unwrap failed");
16225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(unwrap_sak);
16235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
16245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
16255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_hexdump(MSG_DEBUG, "\tAES Key Unwrap of SAK:", unwrap_sak, sak_len);
16265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
16275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	conf = os_zalloc(sizeof(*conf));
16285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!conf) {
16295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY-%s: Out of memory", __func__);
16305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(unwrap_sak);
16315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
16325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
16335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	conf->key_len = sak_len;
16345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
16355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	conf->key = os_zalloc(conf->key_len);
16365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!conf->key) {
16375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY-%s: Out of memory", __func__);
16385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(unwrap_sak);
16395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(conf);
16405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
16415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
16425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
16435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(conf->key, unwrap_sak, conf->key_len);
16445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
16455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(&sak_ki.mi, &participant->current_peer_id.mi,
16465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		  sizeof(sak_ki.mi));
16475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	sak_ki.kn = be_to_host32(body->kn);
16485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
16495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(conf->ki.mi, sak_ki.mi, MI_LEN);
16505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	conf->ki.kn = sak_ki.kn;
16515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	conf->an = body->dan;
16525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	conf->offset = body->confid_offset;
16535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	conf->rx = TRUE;
16545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	conf->tx = TRUE;
16555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
16565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	sa_key = ieee802_1x_kay_init_data_key(conf);
16575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!sa_key) {
16585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(unwrap_sak);
16595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(conf->key);
16605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(conf);
16615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
16625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
16635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
16645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_add(&participant->sak_list, &sa_key->list);
16655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
16665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_cp_set_ciphersuite(
16675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->kay->cp,
16685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		cipher_suite_tbl[participant->kay->macsec_csindex].id);
16695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_cp_sm_step(participant->kay->cp);
16705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_cp_set_offset(participant->kay->cp, body->confid_offset);
16715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_cp_sm_step(participant->kay->cp);
16725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_cp_set_distributedki(participant->kay->cp, &sak_ki);
16735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_cp_set_distributedan(participant->kay->cp, body->dan);
16745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_cp_signal_newsak(participant->kay->cp);
16755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_cp_sm_step(participant->kay->cp);
16765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
16775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->to_use_sak = TRUE;
16785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
16795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_free(unwrap_sak);
16805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_free(conf->key);
16815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_free(conf);
16825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
16835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
16845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
16855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
16865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
16875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
16885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_icv_body_present
16895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
16905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic Boolean
16915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_icv_body_present(struct ieee802_1x_mka_participant *participant)
16925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
16935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return TRUE;
16945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
16955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
16965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
16975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
16985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_get_icv_length
16995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
17005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
17015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_get_icv_length(struct ieee802_1x_mka_participant *participant)
17025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
17035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	int length;
17045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
17055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	length = sizeof(struct ieee802_1x_mka_icv_body);
17065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	length += mka_alg_tbl[participant->kay->mka_algindex].icv_len;
17075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
17085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return (length + 0x3) & ~0x3;
17095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
17105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
17115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
17125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
17135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_encode_icv_body -
17145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
17155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
17165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_encode_icv_body(struct ieee802_1x_mka_participant *participant,
17175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			       struct wpabuf *buf)
17185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
17195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_icv_body *body;
17205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	unsigned int length;
17215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	u8 cmac[MAX_ICV_LEN];
17225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
17235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	length = ieee802_1x_mka_get_icv_length(participant);
17245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (length != DEFAULT_ICV_LEN)  {
17255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body = wpabuf_put(buf, MKA_HDR_LEN);
17265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body->type = MKA_ICV_INDICATOR;
17275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		set_mka_param_body_len(body, length - MKA_HDR_LEN);
17285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
17295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
17305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (mka_alg_tbl[participant->kay->mka_algindex].icv_hash(
17315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		    participant->ick.key, wpabuf_head(buf), buf->used, cmac)) {
17325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY, omac1_aes_128 failed");
17335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
17345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
17355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
17365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (length != DEFAULT_ICV_LEN)  {
17375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_memcpy(wpabuf_put(buf, length - MKA_HDR_LEN), cmac,
17385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			  length - MKA_HDR_LEN);
17395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	} else {
17405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_memcpy(wpabuf_put(buf, length), cmac, length);
17415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
17425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
17435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
17445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
17455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
17465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
17475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_decode_icv_body -
17485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
17495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic u8 *
17505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_decode_icv_body(struct ieee802_1x_mka_participant *participant,
17515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			       const u8 *mka_msg, size_t msg_len)
17525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
17535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_hdr *hdr;
17545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_icv_body *body;
17555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t body_len;
17565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t left_len;
17575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	int body_type;
17585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	const u8 *pos;
17595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
17605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	pos = mka_msg;
17615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	left_len = msg_len;
17625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	while (left_len > (MKA_HDR_LEN + DEFAULT_ICV_LEN)) {
17635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		hdr = (struct ieee802_1x_mka_hdr *) pos;
17645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body_len = get_mka_param_body_len(hdr);
17655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body_type = get_mka_param_body_type(hdr);
17665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
17675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (left_len < (body_len + MKA_HDR_LEN))
17685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			break;
17695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
17705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (body_type != MKA_ICV_INDICATOR) {
17715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			left_len -= MKA_HDR_LEN + body_len;
17725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			pos += MKA_HDR_LEN + body_len;
17735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			continue;
17745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
17755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
17765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body = (struct ieee802_1x_mka_icv_body *)pos;
17775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (body_len
17785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			< mka_alg_tbl[participant->kay->mka_algindex].icv_len) {
17795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			return NULL;
17805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
17815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
17825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return body->icv;
17835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
17845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
17855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return (u8 *) (mka_msg + msg_len - DEFAULT_ICV_LEN);
17865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
17875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
17885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
17895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
17905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_decode_dist_cak_body-
17915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
17925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
17935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_decode_dist_cak_body(
17945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant,
17955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	const u8 *mka_msg, size_t msg_len)
17965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
17975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_hdr *hdr;
17985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t body_len;
17995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
18005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	hdr = (struct ieee802_1x_mka_hdr *) mka_msg;
18015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body_len = get_mka_param_body_len(hdr);
18025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (body_len < 28) {
18035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR,
18045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   "KaY: MKA Use SAK Packet Body Length (%d bytes) should be 28 or more octets",
18055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   (int) body_len);
18065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
18075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
18085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
18095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
18105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
18115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
18125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
18135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
18145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_decode_kmd_body -
18155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
18165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
18175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_mka_decode_kmd_body(
18185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant,
18195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	const u8 *mka_msg, size_t msg_len)
18205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
18215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_hdr *hdr;
18225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t body_len;
18235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
18245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	hdr = (struct ieee802_1x_mka_hdr *) mka_msg;
18255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body_len = get_mka_param_body_len(hdr);
18265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (body_len < 5) {
18275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR,
18285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   "KaY: MKA Use SAK Packet Body Length (%d bytes) should be 5 or more octets",
18295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   (int) body_len);
18305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
18315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
18325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
18335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
18345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
18355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
18365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
18375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
18385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_mka_decode_announce_body -
18395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
18405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int ieee802_1x_mka_decode_announce_body(
18415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant,
18425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	const u8 *mka_msg, size_t msg_len)
18435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
18445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
18455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
18465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
18475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
18485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic struct mka_param_body_handler mak_body_handler[] = {
18495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* basic parameter set */
18505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	{
18515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_encode_basic_body,
18525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		NULL,
18535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_basic_body_length,
18545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_basic_body_present
18555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	},
18565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
18575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* live peer list parameter set */
18585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	{
18595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_encode_live_peer_body,
18605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_decode_live_peer_body,
18615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_get_live_peer_length,
18625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_live_peer_body_present
18635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	},
18645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
18655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* potential peer list parameter set */
18665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	{
18675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_encode_potential_peer_body,
18685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_decode_potential_peer_body,
18695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_get_potential_peer_length,
18705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_potential_peer_body_present
18715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	},
18725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
18735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* sak use parameter set */
18745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	{
18755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_encode_sak_use_body,
18765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_decode_sak_use_body,
18775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_get_sak_use_length,
18785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_sak_use_body_present
18795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	},
18805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
18815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* distribute sak parameter set */
18825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	{
18835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_encode_dist_sak_body,
18845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_decode_dist_sak_body,
18855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_get_dist_sak_length,
18865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_dist_sak_body_present
18875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	},
18885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
18895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* distribute cak parameter set */
18905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	{
18915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		NULL,
18925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_decode_dist_cak_body,
18935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		NULL,
18945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		NULL
18955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	},
18965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
18975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* kmd parameter set */
18985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	{
18995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		NULL,
19005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_decode_kmd_body,
19015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		NULL,
19025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		NULL
19035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	},
19045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
19055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* announce parameter set */
19065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	{
19075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		NULL,
19085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_decode_announce_body,
19095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		NULL,
19105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		NULL
19115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	},
19125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
19135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* icv parameter set */
19145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	{
19155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_encode_icv_body,
19165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		NULL,
19175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_get_icv_length,
19185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_mka_icv_body_present
19195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	},
19205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt};
19215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
19225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
19235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
19245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_deinit_data_key -
19255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
19265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtvoid ieee802_1x_kay_deinit_data_key(struct data_key *pkey)
19275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
19285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!pkey)
19295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return;
19305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
19315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	pkey->user--;
19325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (pkey->user > 1)
19335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return;
19345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
19355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_del(&pkey->list);
19365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_free(pkey->key);
19375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_free(pkey);
19385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
19395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
19405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
19415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
19425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_generate_new_sak -
19435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
19445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
19455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_generate_new_sak(struct ieee802_1x_mka_participant *participant)
19465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
19475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct data_key *sa_key = NULL;
19485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct key_conf *conf;
19495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay_peer *peer;
19505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay *kay = participant->kay;
19515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	int ctx_len, ctx_offset;
19525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	u8 *context;
19535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
19545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* check condition for generating a fresh SAK:
19555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 * must have one live peer
19565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 * and MKA life time elapse since last distribution
19575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 * or potential peer is empty
19585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 */
19595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (dl_list_empty(&participant->live_peers)) {
19605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR,
19615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   "KaY: Live peers list must not empty when generating fresh SAK");
19625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
19635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
19645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
19655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* FIXME: A fresh SAK not generated until
19665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 * the live peer list contains at least one peer and
19675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 * MKA life time has elapsed since the prior SAK was first distributed,
19685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 * or the Key server's potential peer is empty
19695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 * but I can't understand the second item, so
19705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 * here only check first item and ingore
19715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 *   && (!dl_list_empty(&participant->potential_peers))) {
19725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 */
19735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if ((time(NULL) - kay->dist_time) < MKA_LIFE_TIME / 1000) {
19745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR,
19755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   "KaY: Life time have not elapsed since prior SAK distributed");
19765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
19775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
19785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
19795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	conf = os_zalloc(sizeof(*conf));
19805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!conf) {
19815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY-%s: Out of memory", __func__);
19825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
19835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
19845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	conf->key_len = cipher_suite_tbl[kay->macsec_csindex].sak_len;
19855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
19865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	conf->key = os_zalloc(conf->key_len);
19875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!conf->key) {
19885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(conf);
19895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY-%s: Out of memory", __func__);
19905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
19915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
19925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
19935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ctx_len = conf->key_len + sizeof(kay->dist_kn);
19945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(peer, &participant->live_peers,
19955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			 struct ieee802_1x_kay_peer, list)
19965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ctx_len += sizeof(peer->mi);
19975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ctx_len += sizeof(participant->mi);
19985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
19995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	context = os_zalloc(ctx_len);
20005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!context) {
20015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(conf->key);
20025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(conf);
20035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
20045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
20055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ctx_offset = 0;
2006fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt	if (os_get_random(context + ctx_offset, conf->key_len) < 0) {
2007fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt		os_free(context);
2008fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt		os_free(conf->key);
2009fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt		os_free(conf);
2010fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt		return -1;
2011fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt	}
20125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ctx_offset += conf->key_len;
20135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(peer, &participant->live_peers,
20145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			 struct ieee802_1x_kay_peer, list) {
20155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_memcpy(context + ctx_offset, peer->mi, sizeof(peer->mi));
20165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ctx_offset += sizeof(peer->mi);
20175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
20185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(context + ctx_offset, participant->mi,
20195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		  sizeof(participant->mi));
20205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ctx_offset += sizeof(participant->mi);
20215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(context + ctx_offset, &kay->dist_kn, sizeof(kay->dist_kn));
20225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
20235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (conf->key_len == 16) {
20245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_sak_128bits_aes_cmac(participant->cak.key,
20255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt						context, ctx_len, conf->key);
20265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	} else if (conf->key_len == 32) {
20275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_sak_128bits_aes_cmac(participant->cak.key,
20285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt						context, ctx_len, conf->key);
20295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	} else {
20305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY: SAK Length not support");
20315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(conf->key);
20325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(conf);
20335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(context);
20345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
20355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
20365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_hexdump(MSG_DEBUG, "KaY: generated new SAK",
20375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		    conf->key, conf->key_len);
20385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
20395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(conf->ki.mi, participant->mi, MI_LEN);
20405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	conf->ki.kn = participant->kay->dist_kn;
20415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	conf->an = participant->kay->dist_an;
20425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	conf->offset = kay->macsec_confidentiality;
20435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	conf->rx = TRUE;
20445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	conf->tx = TRUE;
20455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
20465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	sa_key = ieee802_1x_kay_init_data_key(conf);
20475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!sa_key) {
20485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(conf->key);
20495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(conf);
20505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(context);
20515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
20525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
20535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->new_key = sa_key;
20545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
20555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_add(&participant->sak_list, &sa_key->list);
20565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_cp_set_ciphersuite(participant->kay->cp,
20575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				      cipher_suite_tbl[kay->macsec_csindex].id);
20585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_cp_sm_step(kay->cp);
20595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_cp_set_offset(kay->cp, conf->offset);
20605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_cp_sm_step(kay->cp);
20615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_cp_set_distributedki(kay->cp, &conf->ki);
20625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_cp_set_distributedan(kay->cp, conf->an);
20635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_cp_signal_newsak(kay->cp);
20645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_cp_sm_step(kay->cp);
20655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
20665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(peer, &participant->live_peers,
20675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			 struct ieee802_1x_kay_peer, list)
20685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		peer->sak_used = FALSE;
20695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
20705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->kay->dist_kn++;
20715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->kay->dist_an++;
20725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (participant->kay->dist_an > 3)
20735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->kay->dist_an = 0;
20745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
20755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->kay->dist_time = time(NULL);
20765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
20775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_free(conf->key);
20785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_free(conf);
20795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_free(context);
20805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
20815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
20825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
20835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
20845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
20855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_elect_key_server - elect the key server
20865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * when to elect: whenever the live peers list changes
20875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
20885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
20895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_elect_key_server(struct ieee802_1x_mka_participant *participant)
20905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
20915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay_peer *peer;
20925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay_peer *key_server = NULL;
20935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay *kay = participant->kay;
20945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	Boolean i_is_key_server;
20955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	int i;
20965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
20975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (participant->is_obliged_key_server) {
20985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->new_sak = TRUE;
20995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->to_dist_sak = FALSE;
21005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_cp_set_electedself(kay->cp, TRUE);
21015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return 0;
21025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
21035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
21045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* elect the key server among the peers */
21055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(peer, &participant->live_peers,
21065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			 struct ieee802_1x_kay_peer, list) {
21075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (!peer->is_key_server)
21085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			continue;
21095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
21105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (!key_server) {
21115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			key_server = peer;
21125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			continue;
21135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
21145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
21155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (peer->key_server_priority <
21165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		    key_server->key_server_priority) {
21175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			key_server = peer;
21185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		} else if (peer->key_server_priority ==
21195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   key_server->key_server_priority) {
21205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			for (i = 0; i < 6; i++) {
21215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				if (peer->sci.addr[i] <
21225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				    key_server->sci.addr[i])
21235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					key_server = peer;
21245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			}
21255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
21265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
21275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
21285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* elect the key server between me and the above elected peer */
21295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	i_is_key_server = FALSE;
21305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (key_server && participant->can_be_key_server) {
21315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (kay->actor_priority
21325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   < key_server->key_server_priority) {
21335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			i_is_key_server = TRUE;
21345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		} else if (kay->actor_priority
21355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					== key_server->key_server_priority) {
21365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			for (i = 0; i < 6; i++) {
21375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				if (kay->actor_sci.addr[i]
21385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					< key_server->sci.addr[i]) {
21395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					i_is_key_server = TRUE;
21405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				}
21415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			}
21425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
21435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
21445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
21455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!key_server && !i_is_key_server) {
21465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->principal = FALSE;
21475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->is_key_server = FALSE;
21485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->is_elected = FALSE;
21495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return 0;
21505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
21515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
21525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (i_is_key_server) {
21535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_cp_set_electedself(kay->cp, TRUE);
21545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (os_memcmp(&kay->key_server_sci, &kay->actor_sci,
21555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			      sizeof(kay->key_server_sci))) {
21565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_cp_signal_chgdserver(kay->cp);
21575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_cp_sm_step(kay->cp);
21585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
21595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
21605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->is_key_server = TRUE;
21615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->principal = TRUE;
21625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->new_sak = TRUE;
21635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_DEBUG, "KaY: I is elected as key server");
21645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->to_dist_sak = FALSE;
21655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->is_elected = TRUE;
21665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
21675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_memcpy(&kay->key_server_sci, &kay->actor_sci,
21685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			  sizeof(kay->key_server_sci));
21695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->key_server_priority = kay->actor_priority;
21705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
21715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
21725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (key_server) {
21735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_cp_set_electedself(kay->cp, FALSE);
21745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (os_memcmp(&kay->key_server_sci, &key_server->sci,
21755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			      sizeof(kay->key_server_sci))) {
21765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_cp_signal_chgdserver(kay->cp);
21775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_cp_sm_step(kay->cp);
21785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
21795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
21805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->is_key_server = FALSE;
21815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->principal = TRUE;
21825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->is_elected = TRUE;
21835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
21845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_memcpy(&kay->key_server_sci, &key_server->sci,
21855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			  sizeof(kay->key_server_sci));
21865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->key_server_priority = key_server->key_server_priority;
21875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
21885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
21895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
21905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
21915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
21925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
21935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
21945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_decide_macsec_use - the key server determinate
21955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt *		 how to use MACsec: whether use MACsec and its capability
21965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * protectFrames will be advised if the key server and one of its live peers are
21975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * MACsec capable and one of those request MACsec protection
21985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
21995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
22005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_decide_macsec_use(
22015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant)
22025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
22035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay *kay = participant->kay;
22045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay_peer *peer;
22055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	enum macsec_cap less_capability;
22065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	Boolean has_peer;
22075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
22085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!participant->is_key_server)
22095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
22105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
22115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* key server self is MACsec-desired and requesting MACsec */
22125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!kay->macsec_desired) {
22135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->advised_desired = FALSE;
22145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
22155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
22165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (kay->macsec_capable == MACSEC_CAP_NOT_IMPLEMENTED) {
22175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->advised_desired = FALSE;
22185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
22195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
22205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	less_capability = kay->macsec_capable;
22215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
22225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* at least one of peers is MACsec-desired and requesting MACsec */
22235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	has_peer = FALSE;
22245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(peer, &participant->live_peers,
22255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			 struct ieee802_1x_kay_peer, list) {
22265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (!peer->macsec_desired)
22275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			continue;
22285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
22295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (peer->macsec_capbility == MACSEC_CAP_NOT_IMPLEMENTED)
22305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			continue;
22315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
22325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		less_capability = (less_capability < peer->macsec_capbility) ?
22335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			less_capability : peer->macsec_capbility;
22345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		has_peer = TRUE;
22355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
22365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
22375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (has_peer) {
22385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->advised_desired = TRUE;
22395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->advised_capability = less_capability;
22405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->authenticated = FALSE;
22415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->secured = TRUE;
22425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->failed = FALSE;
22435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_cp_connect_secure(kay->cp);
22445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_cp_sm_step(kay->cp);
22455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	} else {
22465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->advised_desired = FALSE;
22475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->advised_capability = MACSEC_CAP_NOT_IMPLEMENTED;
22485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->to_use_sak = FALSE;
22495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->authenticated = TRUE;
22505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->secured = FALSE;
22515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->failed = FALSE;
22525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->ltx_kn = 0;
22535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->ltx_an = 0;
22545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->lrx_kn = 0;
22555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->lrx_an = 0;
22565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->otx_kn = 0;
22575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->otx_an = 0;
22585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->orx_kn = 0;
22595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->orx_an = 0;
22605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_cp_connect_authenticated(kay->cp);
22615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_cp_sm_step(kay->cp);
22625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
22635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
22645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
22655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
22665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
22675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic const u8 pae_group_addr[ETH_ALEN] = {
22685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	0x01, 0x80, 0xc2, 0x00, 0x00, 0x03
22695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt};
22705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
22715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
22725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
22735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_encode_mkpdu -
22745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
22755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
22765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_encode_mkpdu(struct ieee802_1x_mka_participant *participant,
22775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			    struct wpabuf *pbuf)
22785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
22795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	unsigned int i;
22805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee8023_hdr *ether_hdr;
22815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_hdr *eapol_hdr;
22825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
22835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ether_hdr = wpabuf_put(pbuf, sizeof(*ether_hdr));
22845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(ether_hdr->dest, pae_group_addr, sizeof(ether_hdr->dest));
22855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(ether_hdr->src, participant->kay->actor_sci.addr,
22865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		  sizeof(ether_hdr->dest));
22875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ether_hdr->ethertype = host_to_be16(ETH_P_EAPOL);
22885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
22895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	eapol_hdr = wpabuf_put(pbuf, sizeof(*eapol_hdr));
22905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	eapol_hdr->version = EAPOL_VERSION;
22915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	eapol_hdr->type = IEEE802_1X_TYPE_EAPOL_MKA;
22925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	eapol_hdr->length = host_to_be16(pbuf->size - pbuf->used);
22935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
22945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	for (i = 0; i < ARRAY_SIZE(mak_body_handler); i++) {
22955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (mak_body_handler[i].body_present &&
22965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		    mak_body_handler[i].body_present(participant)) {
22975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			if (mak_body_handler[i].body_tx(participant, pbuf))
22985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				return -1;
22995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
23005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
23015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
23025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
23035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
23045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
23055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
23065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_participant_send_mkpdu -
23075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
23085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int
23095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_participant_send_mkpdu(
23105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant)
23115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
23125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct wpabuf *buf;
23135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay *kay = participant->kay;
23145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t length = 0;
23155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	unsigned int i;
23165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
23175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "KaY: to enpacket and send the MKPDU");
23185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	length += sizeof(struct ieee802_1x_hdr) + sizeof(struct ieee8023_hdr);
23195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	for (i = 0; i < ARRAY_SIZE(mak_body_handler); i++) {
23205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (mak_body_handler[i].body_present &&
23215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		    mak_body_handler[i].body_present(participant))
23225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			length += mak_body_handler[i].body_length(participant);
23235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
23245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
23255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	buf = wpabuf_alloc(length);
23265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!buf) {
23275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY: out of memory");
23285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
23295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
23305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
23315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (ieee802_1x_kay_encode_mkpdu(participant, buf)) {
23325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY: encode mkpdu fail!");
23335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
23345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
23355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
23365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	l2_packet_send(kay->l2_mka, NULL, 0, wpabuf_head(buf), wpabuf_len(buf));
23375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpabuf_free(buf);
23385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
23395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->active = TRUE;
23405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->active = TRUE;
23415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
23425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
23435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
23445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
23455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
23465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic void ieee802_1x_kay_deinit_transmit_sa(struct transmit_sa *psa);
23475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
23485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_participant_timer -
23495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
23505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic void ieee802_1x_participant_timer(void *eloop_ctx, void *timeout_ctx)
23515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
23525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant;
23535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay *kay;
23545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay_peer *peer, *pre_peer;
23555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	time_t now = time(NULL);
23565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	Boolean lp_changed;
23575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct receive_sc *rxsc, *pre_rxsc;
23585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct transmit_sa *txsa, *pre_txsa;
23595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
23605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant = (struct ieee802_1x_mka_participant *)eloop_ctx;
23615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay = participant->kay;
23625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (participant->cak_life) {
23635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (now > participant->cak_life) {
23645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			kay->authenticated = FALSE;
23655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			kay->secured = FALSE;
23665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			kay->failed = TRUE;
23675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_kay_delete_mka(kay, &participant->ckn);
23685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			return;
23695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
23705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
23715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
23725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* should delete MKA instance if there are not live peers
23735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 * when the MKA life elapsed since its creating */
23745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (participant->mka_life) {
23755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (dl_list_empty(&participant->live_peers)) {
23765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			if (now > participant->mka_life) {
23775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				kay->authenticated = FALSE;
23785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				kay->secured = FALSE;
23795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				kay->failed = TRUE;
23805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				ieee802_1x_kay_delete_mka(kay,
23815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt							  &participant->ckn);
23825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				return;
23835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			}
23845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		} else {
23855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->mka_life = 0;
23865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
23875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
23885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
23895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	lp_changed = FALSE;
23905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each_safe(peer, pre_peer, &participant->live_peers,
23915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			      struct ieee802_1x_kay_peer, list) {
23925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (now > peer->expire) {
23935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			wpa_printf(MSG_DEBUG, "KaY: Live peer removed");
23945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			wpa_hexdump(MSG_DEBUG, "\tMI: ", peer->mi,
23955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				    sizeof(peer->mi));
23965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			wpa_printf(MSG_DEBUG, "\tMN: %d", peer->mn);
23975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			dl_list_for_each_safe(rxsc, pre_rxsc,
23985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					      &participant->rxsc_list,
23995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					      struct receive_sc, list) {
24005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				if (os_memcmp(&rxsc->sci, &peer->sci,
24015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					      sizeof(rxsc->sci)) == 0) {
24025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					secy_delete_receive_sc(kay, rxsc);
24035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					ieee802_1x_kay_deinit_receive_sc(
24045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt						participant, rxsc);
24055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				}
24065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			}
24075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			dl_list_del(&peer->list);
24085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			os_free(peer);
24095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			lp_changed = TRUE;
24105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
24115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
24125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
24135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (lp_changed) {
24145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (dl_list_empty(&participant->live_peers)) {
24155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->advised_desired = FALSE;
24165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->advised_capability =
24175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				MACSEC_CAP_NOT_IMPLEMENTED;
24185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->to_use_sak = FALSE;
24195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			kay->authenticated = TRUE;
24205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			kay->secured = FALSE;
24215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			kay->failed = FALSE;
24225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			kay->ltx_kn = 0;
24235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			kay->ltx_an = 0;
24245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			kay->lrx_kn = 0;
24255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			kay->lrx_an = 0;
24265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			kay->otx_kn = 0;
24275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			kay->otx_an = 0;
24285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			kay->orx_kn = 0;
24295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			kay->orx_an = 0;
24305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			dl_list_for_each_safe(txsa, pre_txsa,
24315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					      &participant->txsc->sa_list,
24325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					      struct transmit_sa, list) {
24335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				secy_disable_transmit_sa(kay, txsa);
24345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				ieee802_1x_kay_deinit_transmit_sa(txsa);
24355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			}
24365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
24375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_cp_connect_authenticated(kay->cp);
24385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_cp_sm_step(kay->cp);
24395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		} else {
24405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_kay_elect_key_server(participant);
24415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_kay_decide_macsec_use(participant);
24425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
24435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
24445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
24455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each_safe(peer, pre_peer, &participant->potential_peers,
24465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			      struct ieee802_1x_kay_peer, list) {
24475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (now > peer->expire) {
24485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			wpa_printf(MSG_DEBUG, "KaY: Potential peer removed");
24495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			wpa_hexdump(MSG_DEBUG, "\tMI: ", peer->mi,
24505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				    sizeof(peer->mi));
24515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			wpa_printf(MSG_DEBUG, "\tMN: %d", peer->mn);
24525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			dl_list_del(&peer->list);
24535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			os_free(peer);
24545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
24555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
24565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
24575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (participant->new_sak) {
24585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (!ieee802_1x_kay_generate_new_sak(participant))
24595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->to_dist_sak = TRUE;
24605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
24615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->new_sak = FALSE;
24625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
24635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
24645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (participant->retry_count < MAX_RETRY_CNT) {
24655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_participant_send_mkpdu(participant);
24665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->retry_count++;
24675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
24685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
24695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	eloop_register_timeout(MKA_HELLO_TIME / 1000, 0,
24705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			       ieee802_1x_participant_timer,
24715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			       participant, NULL);
24725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
24735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
24745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
24755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
24765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_init_transmit_sa -
24775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
24785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic struct transmit_sa *
24795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_init_transmit_sa(struct transmit_sc *psc, u8 an, u32 next_PN,
24805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				struct data_key *key)
24815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
24825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct transmit_sa *psa;
24835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
24845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	key->tx_latest = TRUE;
24855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	key->rx_latest = TRUE;
24865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
24875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	psa = os_zalloc(sizeof(*psa));
24885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!psa) {
24895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "%s: out of memory", __func__);
24905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return NULL;
24915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
24925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
24935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (key->confidentiality_offset >= CONFIDENTIALITY_OFFSET_0 &&
24945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	    key->confidentiality_offset <= CONFIDENTIALITY_OFFSET_50)
24955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		psa->confidentiality = TRUE;
24965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	else
24975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		psa->confidentiality = FALSE;
24985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
24995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	psa->an = an;
25005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	psa->pkey = key;
25015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	psa->next_pn = next_PN;
25025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	psa->sc = psc;
25035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
25045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_get_time(&psa->created_time);
25055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	psa->in_use = FALSE;
25065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
25075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_add(&psc->sa_list, &psa->list);
25085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG,
25095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		   "KaY: Create transmit SA(an: %d, next_PN: %u) of SC(channel: %d)",
25105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		   (int) an, next_PN, psc->channel);
25115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
25125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return psa;
25135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
25145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
25155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
25165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
25175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_deinit_transmit_sa -
25185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
25195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic void ieee802_1x_kay_deinit_transmit_sa(struct transmit_sa *psa)
25205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
25215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	psa->pkey = NULL;
25225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG,
25235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		   "KaY: Delete transmit SA(an: %d) of SC(channel: %d)",
25245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		   psa->an, psa->sc->channel);
25255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_del(&psa->list);
25265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_free(psa);
25275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
25285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
25295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
25305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
25315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * init_transmit_sc -
25325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
25335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic struct transmit_sc *
25345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_init_transmit_sc(const struct ieee802_1x_mka_sci *sci,
25355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				int channel)
25365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
25375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct transmit_sc *psc;
25385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
25395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	psc = os_zalloc(sizeof(*psc));
25405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!psc) {
25415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "%s: out of memory", __func__);
25425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return NULL;
25435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
25445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(&psc->sci, sci, sizeof(psc->sci));
25455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	psc->channel = channel;
25465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
25475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_get_time(&psc->created_time);
25485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	psc->transmitting = FALSE;
25495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	psc->encoding_sa = FALSE;
25505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	psc->enciphering_sa = FALSE;
25515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
25525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_init(&psc->sa_list);
25535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "KaY: Create transmit SC(channel: %d)", channel);
25545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_hexdump(MSG_DEBUG, "SCI: ", (u8 *)sci , sizeof(*sci));
25555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
25565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return psc;
25575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
25585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
25595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
25605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
25615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_deinit_transmit_sc -
25625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
25635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic void
25645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_deinit_transmit_sc(
25655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant, struct transmit_sc *psc)
25665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
25675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct transmit_sa *psa, *tmp;
25685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
25695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "KaY: Delete transmit SC(channel: %d)",
25705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		   psc->channel);
25715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each_safe(psa, tmp, &psc->sa_list, struct transmit_sa,
25725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			      list) {
25735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		secy_disable_transmit_sa(participant->kay, psa);
25745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_kay_deinit_transmit_sa(psa);
25755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
25765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
25775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_free(psc);
25785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
25795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
25805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
25815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/****************** Interface between CP and KAY *********************/
25825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
25835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_set_latest_sa_attr -
25845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
25855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtint ieee802_1x_kay_set_latest_sa_attr(struct ieee802_1x_kay *kay,
25865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				      struct ieee802_1x_mka_ki *lki, u8 lan,
25875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				      Boolean ltx, Boolean lrx)
25885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
25895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *principal;
25905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
25915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	principal = ieee802_1x_kay_get_principal_participant(kay);
25925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!principal)
25935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
25945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
25955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!lki)
25965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_memset(&principal->lki, 0, sizeof(principal->lki));
25975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	else
25985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_memcpy(&principal->lki, lki, sizeof(principal->lki));
25995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
26005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	principal->lan = lan;
26015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	principal->ltx = ltx;
26025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	principal->lrx = lrx;
26035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!lki) {
26045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->ltx_kn = 0;
26055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->lrx_kn = 0;
26065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	} else {
26075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->ltx_kn = lki->kn;
26085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->lrx_kn = lki->kn;
26095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
26105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->ltx_an = lan;
26115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->lrx_an = lan;
26125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
26135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
26145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
26155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
26165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
26175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
26185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_set_old_sa_attr -
26195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
26205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtint ieee802_1x_kay_set_old_sa_attr(struct ieee802_1x_kay *kay,
26215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				   struct ieee802_1x_mka_ki *oki,
26225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				   u8 oan, Boolean otx, Boolean orx)
26235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
26245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *principal;
26255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
26265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	principal = ieee802_1x_kay_get_principal_participant(kay);
26275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!principal)
26285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
26295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
26305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!oki)
26315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_memset(&principal->oki, 0, sizeof(principal->oki));
26325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	else
26335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_memcpy(&principal->oki, oki, sizeof(principal->oki));
26345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
26355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	principal->oan = oan;
26365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	principal->otx = otx;
26375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	principal->orx = orx;
26385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
26395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!oki) {
26405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->otx_kn = 0;
26415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->orx_kn = 0;
26425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	} else {
26435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->otx_kn = oki->kn;
26445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->orx_kn = oki->kn;
26455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
26465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->otx_an = oan;
26475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->orx_an = oan;
26485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
26495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
26505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
26515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
26525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
26535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
26545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_create_sas -
26555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
26565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtint ieee802_1x_kay_create_sas(struct ieee802_1x_kay *kay,
26575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			      struct ieee802_1x_mka_ki *lki)
26585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
26595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct data_key *sa_key, *latest_sak;
26605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *principal;
26615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct receive_sc *rxsc;
26625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct receive_sa *rxsa;
26635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct transmit_sa *txsa;
26645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
26655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	principal = ieee802_1x_kay_get_principal_participant(kay);
26665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!principal)
26675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
26685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
26695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	latest_sak = NULL;
26705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(sa_key, &principal->sak_list, struct data_key, list) {
26715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (is_ki_equal(&sa_key->key_identifier, lki)) {
26725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			sa_key->rx_latest = TRUE;
26735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			sa_key->tx_latest = TRUE;
26745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			latest_sak = sa_key;
26755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			principal->to_use_sak = TRUE;
26765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		} else {
26775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			sa_key->rx_latest = FALSE;
26785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			sa_key->tx_latest = FALSE;
26795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
26805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
26815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!latest_sak) {
26825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "lki related sak not found");
26835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
26845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
26855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
26865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(rxsc, &principal->rxsc_list, struct receive_sc, list) {
26875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		rxsa = ieee802_1x_kay_init_receive_sa(rxsc, latest_sak->an, 1,
26885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt						      latest_sak);
26895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (!rxsa)
26905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			return -1;
26915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
26925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		secy_create_receive_sa(kay, rxsa);
26935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
26945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
26955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	txsa = ieee802_1x_kay_init_transmit_sa(principal->txsc, latest_sak->an,
26965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					       1, latest_sak);
26975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!txsa)
26985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
26995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
27005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	secy_create_transmit_sa(kay, txsa);
27015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
27025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
27035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
27045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
27055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
27065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
27075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
27085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
27095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_delete_sas -
27105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
27115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtint ieee802_1x_kay_delete_sas(struct ieee802_1x_kay *kay,
27125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			      struct ieee802_1x_mka_ki *ki)
27135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
27145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct data_key *sa_key, *pre_key;
27155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct transmit_sa *txsa, *pre_txsa;
27165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct receive_sa *rxsa, *pre_rxsa;
27175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct receive_sc *rxsc;
27185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *principal;
27195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
27205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "KaY: Entry into %s", __func__);
27215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	principal = ieee802_1x_kay_get_principal_participant(kay);
27225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!principal)
27235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
27245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
27255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* remove the transmit sa */
27265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each_safe(txsa, pre_txsa, &principal->txsc->sa_list,
27275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			      struct transmit_sa, list) {
27285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (is_ki_equal(&txsa->pkey->key_identifier, ki)) {
27295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			secy_disable_transmit_sa(kay, txsa);
27305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_kay_deinit_transmit_sa(txsa);
27315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
27325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
27335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
27345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* remove the receive sa */
27355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(rxsc, &principal->rxsc_list, struct receive_sc, list) {
27365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		dl_list_for_each_safe(rxsa, pre_rxsa, &rxsc->sa_list,
27375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				      struct receive_sa, list) {
27385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			if (is_ki_equal(&rxsa->pkey->key_identifier, ki)) {
27395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				secy_disable_receive_sa(kay, rxsa);
27405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				ieee802_1x_kay_deinit_receive_sa(rxsa);
27415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			}
27425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
27435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
27445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
27455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* remove the sak */
27465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each_safe(sa_key, pre_key, &principal->sak_list,
27475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			      struct data_key, list) {
27485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (is_ki_equal(&sa_key->key_identifier, ki)) {
27495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_kay_deinit_data_key(sa_key);
27505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			break;
27515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
27525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (principal->new_key == sa_key)
27535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			principal->new_key = NULL;
27545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
27555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
27565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
27575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
27585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
27595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
27605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
27615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_enable_tx_sas -
27625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
27635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtint ieee802_1x_kay_enable_tx_sas(struct ieee802_1x_kay *kay,
27645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				 struct ieee802_1x_mka_ki *lki)
27655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
27665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *principal;
27675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct transmit_sa *txsa;
27685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
27695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	principal = ieee802_1x_kay_get_principal_participant(kay);
27705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!principal)
27715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
27725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
27735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(txsa, &principal->txsc->sa_list, struct transmit_sa,
27745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			 list) {
27755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (is_ki_equal(&txsa->pkey->key_identifier, lki)) {
27765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			txsa->in_use = TRUE;
27775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			secy_enable_transmit_sa(kay, txsa);
27785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_cp_set_usingtransmitas(
27795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				principal->kay->cp, TRUE);
27805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_cp_sm_step(principal->kay->cp);
27815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
27825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
27835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
27845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
27855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
27865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
27875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
27885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
27895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_enable_rx_sas -
27905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
27915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtint ieee802_1x_kay_enable_rx_sas(struct ieee802_1x_kay *kay,
27925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				 struct ieee802_1x_mka_ki *lki)
27935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
27945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *principal;
27955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct receive_sa *rxsa;
27965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct receive_sc *rxsc;
27975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
27985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	principal = ieee802_1x_kay_get_principal_participant(kay);
27995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!principal)
28005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
28015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
28025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_for_each(rxsc, &principal->rxsc_list, struct receive_sc, list) {
28035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		dl_list_for_each(rxsa, &rxsc->sa_list, struct receive_sa, list)
28045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		{
28055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			if (is_ki_equal(&rxsa->pkey->key_identifier, lki)) {
28065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				rxsa->in_use = TRUE;
28075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				secy_enable_receive_sa(kay, rxsa);
28085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				ieee802_1x_cp_set_usingreceivesas(
28095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					principal->kay->cp, TRUE);
28105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				ieee802_1x_cp_sm_step(principal->kay->cp);
28115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			}
28125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
28135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
28145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
28155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
28165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
28175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
28185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
28195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
28205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_enable_new_info -
28215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
28225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtint ieee802_1x_kay_enable_new_info(struct ieee802_1x_kay *kay)
28235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
28245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *principal;
28255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
28265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	principal = ieee802_1x_kay_get_principal_participant(kay);
28275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!principal)
28285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
28295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
28305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (principal->retry_count < MAX_RETRY_CNT) {
28315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_participant_send_mkpdu(principal);
28325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		principal->retry_count++;
28335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
28345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
28355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
28365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
28375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
28385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
28395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
28405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_cp_conf -
28415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
28425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtint ieee802_1x_kay_cp_conf(struct ieee802_1x_kay *kay,
28435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   struct ieee802_1x_cp_conf *pconf)
28445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
28455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	pconf->protect = kay->macsec_protect;
28465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	pconf->replay_protect = kay->macsec_replay_protect;
28475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	pconf->validate = kay->macsec_validate;
28485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
28495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
28505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
28515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
28525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
28535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
28545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_alloc_cp_sm -
28555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
28565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic struct ieee802_1x_cp_sm *
28575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_alloc_cp_sm(struct ieee802_1x_kay *kay)
28585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
28595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_cp_conf conf;
28605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
28615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memset(&conf, 0, sizeof(conf));
28625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	conf.protect = kay->macsec_protect;
28635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	conf.replay_protect = kay->macsec_replay_protect;
28645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	conf.validate = kay->macsec_validate;
28655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	conf.replay_window = kay->macsec_replay_window;
28665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
28675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return ieee802_1x_cp_sm_init(kay, &conf);
28685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
28695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
28705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
28715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
28725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_mkpdu_sanity_check -
28735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt *     sanity check specified in clause 11.11.2 of IEEE802.1X-2010
28745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
28755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int ieee802_1x_kay_mkpdu_sanity_check(struct ieee802_1x_kay *kay,
28765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					     const u8 *buf, size_t len)
28775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
28785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee8023_hdr *eth_hdr;
28795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_hdr *eapol_hdr;
28805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_hdr *mka_hdr;
28815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_basic_body *body;
28825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t mka_msg_len;
28835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant;
28845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t body_len;
28855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	u8 icv[MAX_ICV_LEN];
28865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	u8 *msg_icv;
28875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
28885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	eth_hdr = (struct ieee8023_hdr *) buf;
28895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	eapol_hdr = (struct ieee802_1x_hdr *) (eth_hdr + 1);
28905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	mka_hdr = (struct ieee802_1x_mka_hdr *) (eapol_hdr + 1);
28915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
28925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* destination address should be not individual address */
28935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (os_memcmp(eth_hdr->dest, pae_group_addr, ETH_ALEN) != 0) {
28945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_MSGDUMP,
28955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   "KaY: ethernet destination address is not PAE group address");
28965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
28975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
28985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
28995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* MKPDU should not less than 32 octets */
29005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	mka_msg_len = be_to_host16(eapol_hdr->length);
29015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (mka_msg_len < 32) {
29025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_MSGDUMP, "KaY: MKPDU is less than 32 octets");
29035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
29045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
29055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* MKPDU should multiple 4 octets */
29065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if ((mka_msg_len % 4) != 0) {
29075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_MSGDUMP,
29085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   "KaY: MKPDU is not multiple of 4 octets");
29095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
29105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
29115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
29125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body = (struct ieee802_1x_mka_basic_body *) mka_hdr;
29135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_mka_dump_basic_body(body);
29145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body_len = get_mka_param_body_len(body);
29155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* EAPOL-MKA body should comprise basic parameter set and ICV */
29165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (mka_msg_len < MKA_HDR_LEN + body_len + DEFAULT_ICV_LEN) {
29175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR,
29185a1480c7c46c4236d93bfd303dde32062bee04acDmitry 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",
29195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   (int) mka_msg_len, (int) MKA_HDR_LEN,
29205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   (int) body_len, DEFAULT_ICV_LEN);
29215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
29225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
29235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
29245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* CKN should be owned by I */
29255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant = ieee802_1x_kay_get_participant(kay, body->ckn);
29265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!participant) {
29275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_DEBUG, "CKN is not included in my CA");
29285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
29295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
29305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
29315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* algorithm agility check */
29325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (os_memcmp(body->algo_agility, mka_algo_agility,
29335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		      sizeof(body->algo_agility)) != 0) {
29345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR,
29355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   "KaY: peer's algorithm agility not supported for me");
29365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
29375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
29385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
29395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* ICV check */
29405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/*
29415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 * The ICV will comprise the final octets of the packet body, whatever
29425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 * its size, not the fixed length 16 octets, indicated by the EAPOL
29435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 * packet body length.
29445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 */
29455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (mka_alg_tbl[kay->mka_algindex].icv_hash(
29465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		    participant->ick.key,
29475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		    buf, len - mka_alg_tbl[kay->mka_algindex].icv_len, icv)) {
29485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY: omac1_aes_128 failed");
29495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
29505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
29515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	msg_icv = ieee802_1x_mka_decode_icv_body(participant, (u8 *) mka_hdr,
29525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt						 mka_msg_len);
29535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
29545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (msg_icv) {
2955c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt		if (os_memcmp_const(msg_icv, icv,
2956c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt				    mka_alg_tbl[kay->mka_algindex].icv_len) !=
2957c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt		    0) {
29585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			wpa_printf(MSG_ERROR,
29595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				   "KaY: Computed ICV is not equal to Received ICV");
29605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
29615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
29625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	} else {
29635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY: No ICV");
29645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
29655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
29665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
29675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
29685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
29695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
29705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
29715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
29725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_decode_mkpdu -
29735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
29745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic int ieee802_1x_kay_decode_mkpdu(struct ieee802_1x_kay *kay,
29755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				       const u8 *buf, size_t len)
29765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
29775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant;
29785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_hdr *hdr;
29795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t body_len;
29805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	size_t left_len;
29815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	int body_type;
29825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	int i;
29835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	const u8 *pos;
29845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	Boolean my_included;
29855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	Boolean handled[256];
29865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
29875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (ieee802_1x_kay_mkpdu_sanity_check(kay, buf, len))
29885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
29895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
29905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* handle basic parameter set */
29915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	pos = buf + sizeof(struct ieee8023_hdr) + sizeof(struct ieee802_1x_hdr);
29925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	left_len = len - sizeof(struct ieee8023_hdr) -
29935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		sizeof(struct ieee802_1x_hdr);
29945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant = ieee802_1x_mka_decode_basic_body(kay, pos, left_len);
29955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!participant)
29965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
29975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
29985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* to skip basic parameter set */
29995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	hdr = (struct ieee802_1x_mka_hdr *) pos;
30005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	body_len = get_mka_param_body_len(hdr);
30015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	pos += body_len + MKA_HDR_LEN;
30025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	left_len -= body_len + MKA_HDR_LEN;
30035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
30045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* check i am in the peer's peer list */
30055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	my_included = ieee802_1x_mka_i_in_peerlist(participant, pos, left_len);
30065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (my_included) {
30075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		/* accept the peer as live peer */
30085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (!ieee802_1x_kay_is_in_peer(
30095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			    participant,
30105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			    participant->current_peer_id.mi)) {
30115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			if (!ieee802_1x_kay_create_live_peer(
30125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				    participant,
30135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				    participant->current_peer_id.mi,
30145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				    participant->current_peer_id.mn))
30155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				return -1;
30165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_kay_elect_key_server(participant);
30175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_kay_decide_macsec_use(participant);
30185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
30195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (ieee802_1x_kay_is_in_potential_peer(
30205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			    participant, participant->current_peer_id.mi)) {
30215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_kay_move_live_peer(
30225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				participant, participant->current_peer_id.mi,
30235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				participant->current_peer_id.mn);
30245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_kay_elect_key_server(participant);
30255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_kay_decide_macsec_use(participant);
30265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
30275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
30285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
30295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/*
30305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 * Handle other parameter set than basic parameter set.
30315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 * Each parameter set should be present only once.
30325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	 */
30335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	for (i = 0; i < 256; i++)
30345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		handled[i] = FALSE;
30355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
30365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	handled[0] = TRUE;
30375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	while (left_len > MKA_HDR_LEN + DEFAULT_ICV_LEN) {
30385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		hdr = (struct ieee802_1x_mka_hdr *) pos;
30395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body_len = get_mka_param_body_len(hdr);
30405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		body_type = get_mka_param_body_type(hdr);
30415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
30425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (body_type == MKA_ICV_INDICATOR)
30435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			return 0;
30445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
30455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (left_len < (MKA_HDR_LEN + body_len + DEFAULT_ICV_LEN)) {
30465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			wpa_printf(MSG_ERROR,
30475a1480c7c46c4236d93bfd303dde32062bee04acDmitry 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",
30485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				   (int) left_len, (int) MKA_HDR_LEN,
30495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				   (int) body_len, DEFAULT_ICV_LEN);
30505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			goto next_para_set;
30515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
30525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
30535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (handled[body_type])
30545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			goto next_para_set;
30555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
30565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		handled[body_type] = TRUE;
30575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (mak_body_handler[body_type].body_rx) {
30585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			mak_body_handler[body_type].body_rx
30595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				(participant, pos, left_len);
30605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		} else {
30615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			wpa_printf(MSG_ERROR,
30625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				   "The type %d not supported in this MKA version %d",
30635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				   body_type, MKA_VERSION_ID);
30645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
30655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
30665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtnext_para_set:
30675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		pos += body_len + MKA_HDR_LEN;
30685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		left_len -= body_len + MKA_HDR_LEN;
30695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
30705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
30715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->active = TRUE;
30725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->retry_count = 0;
30735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->active = TRUE;
30745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
30755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
30765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
30775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
30785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
30795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
30805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstatic void kay_l2_receive(void *ctx, const u8 *src_addr, const u8 *buf,
30815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   size_t len)
30825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
30835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay *kay = ctx;
30845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee8023_hdr *eth_hdr;
30855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_hdr *eapol_hdr;
30865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
30875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* must contain at least ieee8023_hdr + ieee802_1x_hdr */
30885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (len < sizeof(*eth_hdr) + sizeof(*eapol_hdr)) {
30895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_MSGDUMP, "KaY: EAPOL frame too short (%lu)",
30905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   (unsigned long) len);
30915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return;
30925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
30935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
30945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	eth_hdr = (struct ieee8023_hdr *) buf;
30955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	eapol_hdr = (struct ieee802_1x_hdr *) (eth_hdr + 1);
30965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (len != sizeof(*eth_hdr) + sizeof(*eapol_hdr) +
30975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	    ntohs(eapol_hdr->length)) {
30985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_MSGDUMP, "KAY: EAPOL MPDU is invalid: (%lu-%lu)",
30995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   (unsigned long) len,
31005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   (unsigned long) ntohs(eapol_hdr->length));
31015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return;
31025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
31035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
31045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (eapol_hdr->version < EAPOL_VERSION) {
31055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_MSGDUMP, "KaY: version %d does not support MKA",
31065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   eapol_hdr->version);
31075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return;
31085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
31095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (ntohs(eth_hdr->ethertype) != ETH_P_PAE ||
31105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	    eapol_hdr->type != IEEE802_1X_TYPE_EAPOL_MKA)
31115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return;
31125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
31135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_hexdump(MSG_DEBUG, "RX EAPOL-MKA: ", buf, len);
31145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (dl_list_empty(&kay->participant_list)) {
31155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY: no MKA participant instance");
31165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return;
31175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
31185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
31195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_kay_decode_mkpdu(kay, buf, len);
31205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
31215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
31225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
31235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
31245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_init -
31255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
31265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstruct ieee802_1x_kay *
31275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_init(struct ieee802_1x_kay_ctx *ctx, enum macsec_policy policy,
31285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		    const char *ifname, const u8 *addr)
31295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
31305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay *kay;
31315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
31325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay = os_zalloc(sizeof(*kay));
31335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!kay) {
31345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY-%s: out of memory", __func__);
31355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return NULL;
31365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
31375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
31385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->ctx = ctx;
31395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
31405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->enable = TRUE;
31415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->active = FALSE;
31425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
31435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->authenticated = FALSE;
31445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->secured = FALSE;
31455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->failed = FALSE;
31465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->policy = policy;
31475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
31485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_strlcpy(kay->if_name, ifname, IFNAMSIZ);
31495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(kay->actor_sci.addr, addr, ETH_ALEN);
31505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->actor_sci.port = 0x0001;
31515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->actor_priority = DEFAULT_PRIO_NOT_KEY_SERVER;
31525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
31535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* While actor acts as a key server, shall distribute sakey */
31545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->dist_kn = 1;
31555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->dist_an = 0;
31565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->dist_time = 0;
31575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
31585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->pn_exhaustion = PENDING_PN_EXHAUSTION;
31595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->macsec_csindex = DEFAULT_CS_INDEX;
31605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->mka_algindex = DEFAULT_MKA_ALG_INDEX;
31615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->mka_version = MKA_VERSION_ID;
31625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
31635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(kay->algo_agility, mka_algo_agility,
31645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		  sizeof(kay->algo_agility));
31655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
31665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_init(&kay->participant_list);
31675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
31685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (policy == DO_NOT_SECURE) {
31695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->macsec_capable = MACSEC_CAP_NOT_IMPLEMENTED;
31705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->macsec_desired = FALSE;
31715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->macsec_protect = FALSE;
3172fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt		kay->macsec_validate = Disabled;
31735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->macsec_replay_protect = FALSE;
31745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->macsec_replay_window = 0;
31755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->macsec_confidentiality = CONFIDENTIALITY_NONE;
31765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	} else {
31775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->macsec_capable = MACSEC_CAP_INTEG_AND_CONF_0_30_50;
31785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->macsec_desired = TRUE;
31795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->macsec_protect = TRUE;
3180fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt		kay->macsec_validate = Strict;
31815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->macsec_replay_protect = FALSE;
31825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->macsec_replay_window = 0;
31835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->macsec_confidentiality = CONFIDENTIALITY_OFFSET_0;
31845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
31855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
31865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "KaY: state machine created");
31875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
31885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* Initialize the SecY must be prio to CP, as CP will control SecY */
31895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	secy_init_macsec(kay);
31905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	secy_get_available_transmit_sc(kay, &kay->sc_ch);
31915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
31925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "KaY: secy init macsec done");
31935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
31945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* init CP */
31955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->cp = ieee802_1x_kay_alloc_cp_sm(kay);
31965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (kay->cp == NULL) {
31975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_kay_deinit(kay);
31985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return NULL;
31995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
32005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
32015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (policy == DO_NOT_SECURE) {
32025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_cp_connect_authenticated(kay->cp);
32035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_cp_sm_step(kay->cp);
32045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	} else {
32055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->l2_mka = l2_packet_init(kay->if_name, NULL, ETH_P_PAE,
32065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					     kay_l2_receive, kay, 1);
32075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (kay->l2_mka == NULL) {
32085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			wpa_printf(MSG_WARNING,
32095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				   "KaY: Failed to initialize L2 packet processing for MKA packet");
32105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			ieee802_1x_kay_deinit(kay);
32115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			return NULL;
32125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
32135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
32145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
32155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return kay;
32165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
32175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
32185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
32195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
32205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_deinit -
32215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
32225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtvoid
32235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_deinit(struct ieee802_1x_kay *kay)
32245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
32255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant;
32265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
32275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!kay)
32285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return;
32295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
32305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "KaY: state machine removed");
32315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
32325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	while (!dl_list_empty(&kay->participant_list)) {
32335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant = dl_list_entry(kay->participant_list.next,
32345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					    struct ieee802_1x_mka_participant,
32355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt					    list);
32365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_kay_delete_mka(kay, &participant->ckn);
32375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
32385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
32395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_cp_sm_deinit(kay->cp);
32405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	secy_deinit_macsec(kay);
32415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
32425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (kay->l2_mka) {
32435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		l2_packet_deinit(kay->l2_mka);
32445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->l2_mka = NULL;
32455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
32465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
32475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_free(kay->ctx);
32485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_free(kay);
32495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
32505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
32515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
32525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
32535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_create_mka -
32545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
32555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtstruct ieee802_1x_mka_participant *
32565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_create_mka(struct ieee802_1x_kay *kay, struct mka_key_name *ckn,
32575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			  struct mka_key *cak, u32 life,
32585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			  enum mka_created_mode mode, Boolean is_authenticator)
32595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
32605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant;
32615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	unsigned int usecs;
32625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
32635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!kay || !ckn || !cak) {
32645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY: ckn or cak is null");
32655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return NULL;
32665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
32675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
32685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (cak->len != mka_alg_tbl[kay->mka_algindex].cak_len) {
32695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY: CAK length not follow key schema");
32705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return NULL;
32715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
32725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (ckn->len > MAX_CKN_LEN) {
32735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY: CKN is out of range(<=32 bytes)");
32745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return NULL;
32755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
32765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!kay->enable) {
32775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY: Now is at disable state");
32785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return NULL;
32795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
32805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
32815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant = os_zalloc(sizeof(*participant));
32825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!participant) {
32835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY-%s: out of memory", __func__);
32845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return NULL;
32855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
32865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
32875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->ckn.len = ckn->len;
32885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(participant->ckn.name, ckn->name, ckn->len);
32895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->cak.len = cak->len;
32905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memcpy(participant->cak.key, cak->key, cak->len);
32915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (life)
32925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->cak_life = life + time(NULL);
32935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
32945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	switch (mode) {
32955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	case EAP_EXCHANGE:
32965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		if (is_authenticator) {
32975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->is_obliged_key_server = TRUE;
32985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->can_be_key_server = TRUE;
32995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->is_key_server = TRUE;
33005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->principal = TRUE;
33015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
33025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			os_memcpy(&kay->key_server_sci, &kay->actor_sci,
33035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				  sizeof(kay->key_server_sci));
33045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			kay->key_server_priority = kay->actor_priority;
33055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->is_elected = TRUE;
33065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		} else {
33075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->is_obliged_key_server = FALSE;
33085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->can_be_key_server = FALSE;
33095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->is_key_server = FALSE;
33105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->is_elected = TRUE;
33115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		}
33125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		break;
33135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
33145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	default:
33155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->is_obliged_key_server = FALSE;
33165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->can_be_key_server = TRUE;
33175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->is_key_server = FALSE;
33185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->is_elected = FALSE;
33195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		break;
33205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
33215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
33225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->cached = FALSE;
33235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
33245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->active = FALSE;
33255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->participant = FALSE;
33265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->retain = FALSE;
33275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->activate = DEFAULT;
33285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
33295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (participant->is_key_server)
33305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->principal = TRUE;
33315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
33325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_init(&participant->live_peers);
33335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_init(&participant->potential_peers);
33345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
33355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->retry_count = 0;
33365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->kay = kay;
33375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
3338fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt	if (os_get_random(participant->mi, sizeof(participant->mi)) < 0)
3339fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt		goto fail;
33405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->mn = 0;
33415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
33425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->lrx = FALSE;
33435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->ltx = FALSE;
33445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->orx = FALSE;
33455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->otx = FALSE;
33465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->to_dist_sak = FALSE;
33475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->to_use_sak = FALSE;
33485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->new_sak = FALSE;
33495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_init(&participant->sak_list);
33505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->new_key = NULL;
33515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_init(&participant->rxsc_list);
33525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->txsc = ieee802_1x_kay_init_transmit_sc(&kay->actor_sci,
33535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt							    kay->sc_ch);
3354fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt	secy_cp_control_protect_frames(kay, kay->macsec_protect);
3355fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt	secy_cp_control_replay(kay, kay->macsec_replay_protect,
3356fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt			       kay->macsec_replay_window);
33575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	secy_create_transmit_sc(kay, participant->txsc);
33585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
33595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* to derive KEK from CAK and CKN */
33605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->kek.len = mka_alg_tbl[kay->mka_algindex].kek_len;
33615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (mka_alg_tbl[kay->mka_algindex].kek_trfm(participant->cak.key,
33625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt						    participant->ckn.name,
33635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt						    participant->ckn.len,
33645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt						    participant->kek.key)) {
33655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY: Derived KEK failed");
33665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		goto fail;
33675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
33685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_hexdump_key(MSG_DEBUG, "KaY: Derived KEK",
33695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->kek.key, participant->kek.len);
33705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
33715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* to derive ICK from CAK and CKN */
33725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->ick.len = mka_alg_tbl[kay->mka_algindex].ick_len;
33735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (mka_alg_tbl[kay->mka_algindex].ick_trfm(participant->cak.key,
33745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt						    participant->ckn.name,
33755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt						    participant->ckn.len,
33765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt						    participant->ick.key)) {
33775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR, "KaY: Derived ICK failed");
33785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		goto fail;
33795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
33805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_hexdump_key(MSG_DEBUG, "KaY: Derived ICK",
33815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			participant->ick.key, participant->ick.len);
33825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
33835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_add(&kay->participant_list, &participant->list);
33845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_hexdump(MSG_DEBUG, "KaY: Participant created:",
33855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		    ckn->name, ckn->len);
33865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
33875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	usecs = os_random() % (MKA_HELLO_TIME * 1000);
33885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	eloop_register_timeout(0, usecs, ieee802_1x_participant_timer,
33895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			       participant, NULL);
33905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->mka_life = MKA_LIFE_TIME / 1000 + time(NULL) +
33915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		usecs / 1000000;
33925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
33935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return participant;
33945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
33955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtfail:
33965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_free(participant);
33975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return NULL;
33985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
33995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
34005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
34015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
34025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_delete_mka -
34035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
34045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtvoid
34055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_delete_mka(struct ieee802_1x_kay *kay, struct mka_key_name *ckn)
34065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
34075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant;
34085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_kay_peer *peer;
34095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct data_key *sak;
34105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct receive_sc *rxsc;
34115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
34125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!kay || !ckn)
34135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return;
34145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
34155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "KaY: participant removed");
34165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
34175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* get the participant */
34185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant = ieee802_1x_kay_get_participant(kay, ckn->name);
34195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!participant) {
34205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_hexdump(MSG_DEBUG, "KaY: participant is not found",
34215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			    ckn->name, ckn->len);
34225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return;
34235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
34245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
34255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	dl_list_del(&participant->list);
34265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
34275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* remove live peer */
34285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	while (!dl_list_empty(&participant->live_peers)) {
34295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		peer = dl_list_entry(participant->live_peers.next,
34305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				     struct ieee802_1x_kay_peer, list);
34315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		dl_list_del(&peer->list);
34325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(peer);
34335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
34345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
34355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* remove potential peer */
34365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	while (!dl_list_empty(&participant->potential_peers)) {
34375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		peer = dl_list_entry(participant->potential_peers.next,
34385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				     struct ieee802_1x_kay_peer, list);
34395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		dl_list_del(&peer->list);
34405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(peer);
34415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
34425a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
34435a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	/* remove sak */
34445a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	while (!dl_list_empty(&participant->sak_list)) {
34455a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		sak = dl_list_entry(participant->sak_list.next,
34465a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				    struct data_key, list);
34475a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		dl_list_del(&sak->list);
34485a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(sak->key);
34495a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		os_free(sak);
34505a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
34515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	while (!dl_list_empty(&participant->rxsc_list)) {
34525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		rxsc = dl_list_entry(participant->rxsc_list.next,
34535a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				     struct receive_sc, list);
34545a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		secy_delete_receive_sc(kay, rxsc);
34555a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		ieee802_1x_kay_deinit_receive_sc(participant, rxsc);
34565a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
34575a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	secy_delete_transmit_sc(kay, participant->txsc);
34585a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	ieee802_1x_kay_deinit_transmit_sc(participant, participant->txsc);
34595a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
34605a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memset(&participant->cak, 0, sizeof(participant->cak));
34615a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memset(&participant->kek, 0, sizeof(participant->kek));
34625a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_memset(&participant->ick, 0, sizeof(participant->ick));
34635a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	os_free(participant);
34645a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
34655a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
34665a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
34675a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
34685a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_mka_participate -
34695a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
34705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtvoid ieee802_1x_kay_mka_participate(struct ieee802_1x_kay *kay,
34715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				    struct mka_key_name *ckn,
34725a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt				    Boolean status)
34735a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
34745a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant;
34755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
34765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!kay || !ckn)
34775a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return;
34785a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
34795a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant = ieee802_1x_kay_get_participant(kay, ckn->name);
34805a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!participant)
34815a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return;
34825a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
34835a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->active = status;
34845a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
34855a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
34865a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
34875a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
34885a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_new_sak -
34895a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
34905a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtint
34915a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_new_sak(struct ieee802_1x_kay *kay)
34925a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
34935a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant;
34945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
34955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!kay)
34965a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
34975a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
34985a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant = ieee802_1x_kay_get_principal_participant(kay);
34995a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!participant)
35005a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
35015a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
35025a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant->new_sak = TRUE;
35035a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	wpa_printf(MSG_DEBUG, "KaY: new SAK signal");
35045a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
35055a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
35065a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
35075a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
35085a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
35095a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt/**
35105a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt * ieee802_1x_kay_change_cipher_suite -
35115a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt */
35125a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtint
35135a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidtieee802_1x_kay_change_cipher_suite(struct ieee802_1x_kay *kay, int cs_index)
35145a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt{
35155a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	struct ieee802_1x_mka_participant *participant;
35165a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
35175a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (!kay)
35185a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
35195a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
35205a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if ((unsigned int) cs_index >= CS_TABLE_SIZE) {
35215a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_ERROR,
35225a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt			   "KaY: Configured cipher suite index is out of range");
35235a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -1;
35245a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
35255a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (kay->macsec_csindex == cs_index)
35265a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		return -2;
35275a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
35285a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (cs_index == 0)
35295a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		kay->macsec_desired = FALSE;
35305a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
35315a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->macsec_csindex = cs_index;
35325a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	kay->macsec_capable = cipher_suite_tbl[kay->macsec_csindex].capable;
35335a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
35345a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	participant = ieee802_1x_kay_get_principal_participant(kay);
35355a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	if (participant) {
35365a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		wpa_printf(MSG_INFO, "KaY: Cipher Suite changed");
35375a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt		participant->new_sak = TRUE;
35385a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	}
35395a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt
35405a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt	return 0;
35415a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt}
3542