Home | History | Annotate | Download | only in pae
      1 /*
      2  * IEEE 802.1X-2010 Key Agree Protocol of PAE state machine
      3  * Copyright (c) 2013, Qualcomm Atheros, Inc.
      4  *
      5  * This software may be distributed under the terms of the BSD license.
      6  * See README for more details.
      7  */
      8 
      9 #include <time.h>
     10 #include "includes.h"
     11 #include "common.h"
     12 #include "list.h"
     13 #include "eloop.h"
     14 #include "wpabuf.h"
     15 #include "state_machine.h"
     16 #include "l2_packet/l2_packet.h"
     17 #include "common/eapol_common.h"
     18 #include "crypto/aes_wrap.h"
     19 #include "ieee802_1x_cp.h"
     20 #include "ieee802_1x_key.h"
     21 #include "ieee802_1x_kay.h"
     22 #include "ieee802_1x_kay_i.h"
     23 #include "ieee802_1x_secy_ops.h"
     24 
     25 
     26 #define DEFAULT_SA_KEY_LEN	16
     27 #define DEFAULT_ICV_LEN		16
     28 #define MAX_ICV_LEN		32  /* 32 bytes, 256 bits */
     29 
     30 #define PENDING_PN_EXHAUSTION 0xC0000000
     31 
     32 #define MKA_ALIGN_LENGTH(len) (((len) + 0x3) & ~0x3)
     33 
     34 /* IEEE Std 802.1X-2010, Table 9-1 - MKA Algorithm Agility */
     35 #define MKA_ALGO_AGILITY_2009 { 0x00, 0x80, 0xC2, 0x01 }
     36 static u8 mka_algo_agility[4] = MKA_ALGO_AGILITY_2009;
     37 
     38 /* IEEE802.1AE-2006 Table 14-1 MACsec Cipher Suites */
     39 static struct macsec_ciphersuite cipher_suite_tbl[] = {
     40 	/* GCM-AES-128 */
     41 	{
     42 		.id = CS_ID_GCM_AES_128,
     43 		.name = CS_NAME_GCM_AES_128,
     44 		.capable = MACSEC_CAP_INTEG_AND_CONF_0_30_50,
     45 		.sak_len = DEFAULT_SA_KEY_LEN,
     46 		.index = 0,
     47 	},
     48 };
     49 #define CS_TABLE_SIZE (ARRAY_SIZE(cipher_suite_tbl))
     50 #define DEFAULT_CS_INDEX  0
     51 
     52 static struct mka_alg mka_alg_tbl[] = {
     53 	{
     54 		.parameter = MKA_ALGO_AGILITY_2009,
     55 
     56 		/* 128-bit CAK, KEK, ICK, ICV */
     57 		.cak_len = DEFAULT_ICV_LEN,
     58 		.kek_len = DEFAULT_ICV_LEN,
     59 		.ick_len = DEFAULT_ICV_LEN,
     60 		.icv_len = DEFAULT_ICV_LEN,
     61 
     62 		.cak_trfm = ieee802_1x_cak_128bits_aes_cmac,
     63 		.ckn_trfm = ieee802_1x_ckn_128bits_aes_cmac,
     64 		.kek_trfm = ieee802_1x_kek_128bits_aes_cmac,
     65 		.ick_trfm = ieee802_1x_ick_128bits_aes_cmac,
     66 		.icv_hash = ieee802_1x_icv_128bits_aes_cmac,
     67 
     68 		.index = 1,
     69 	},
     70 };
     71 #define MKA_ALG_TABLE_SIZE (ARRAY_SIZE(mka_alg_tbl))
     72 
     73 
     74 static int is_ki_equal(struct ieee802_1x_mka_ki *ki1,
     75 		       struct ieee802_1x_mka_ki *ki2)
     76 {
     77 	return os_memcmp(ki1->mi, ki2->mi, MI_LEN) == 0 &&
     78 		ki1->kn == ki2->kn;
     79 }
     80 
     81 
     82 static void set_mka_param_body_len(void *body, unsigned int len)
     83 {
     84 	struct ieee802_1x_mka_hdr *hdr = body;
     85 	hdr->length = (len >> 8) & 0x0f;
     86 	hdr->length1 = len & 0xff;
     87 }
     88 
     89 
     90 static unsigned int get_mka_param_body_len(const void *body)
     91 {
     92 	const struct ieee802_1x_mka_hdr *hdr = body;
     93 	return (hdr->length << 8) | hdr->length1;
     94 }
     95 
     96 
     97 static u8 get_mka_param_body_type(const void *body)
     98 {
     99 	const struct ieee802_1x_mka_hdr *hdr = body;
    100 	return hdr->type;
    101 }
    102 
    103 
    104 /**
    105  * ieee802_1x_mka_dump_basic_body -
    106  */
    107 static void
    108 ieee802_1x_mka_dump_basic_body(struct ieee802_1x_mka_basic_body *body)
    109 {
    110 	size_t body_len;
    111 
    112 	if (!body)
    113 		return;
    114 
    115 	body_len = get_mka_param_body_len(body);
    116 	wpa_printf(MSG_DEBUG, "*** MKA Basic Parameter set ***");
    117 	wpa_printf(MSG_DEBUG, "\tVersion.......: %d", body->version);
    118 	wpa_printf(MSG_DEBUG, "\tPriority......: %d", body->priority);
    119 	wpa_printf(MSG_DEBUG, "\tKeySvr........: %d", body->key_server);
    120 	wpa_printf(MSG_DEBUG, "\tMACSecDesired.: %d", body->macsec_desired);
    121 	wpa_printf(MSG_DEBUG, "\tMACSecCapable.: %d", body->macsec_capability);
    122 	wpa_printf(MSG_DEBUG, "\tBody Length...: %zu", body_len);
    123 	wpa_printf(MSG_DEBUG, "\tSCI MAC.......: " MACSTR,
    124 		   MAC2STR(body->actor_sci.addr));
    125 	wpa_printf(MSG_DEBUG, "\tSCI Port .....: %d",
    126 		   be_to_host16(body->actor_sci.port));
    127 	wpa_hexdump(MSG_DEBUG, "\tMember Id.....:",
    128 		    body->actor_mi, sizeof(body->actor_mi));
    129 	wpa_printf(MSG_DEBUG, "\tMessage Number: %d",
    130 		   be_to_host32(body->actor_mn));
    131 	wpa_hexdump(MSG_DEBUG, "\tAlgo Agility..:",
    132 		    body->algo_agility, sizeof(body->algo_agility));
    133 	wpa_hexdump_ascii(MSG_DEBUG, "\tCAK Name......:", body->ckn,
    134 			  body_len + MKA_HDR_LEN - sizeof(*body));
    135 }
    136 
    137 
    138 /**
    139  * ieee802_1x_mka_dump_peer_body -
    140  */
    141 static void
    142 ieee802_1x_mka_dump_peer_body(struct ieee802_1x_mka_peer_body *body)
    143 {
    144 	size_t body_len;
    145 	size_t i;
    146 	u8 *mi;
    147 	be32 mn;
    148 
    149 	if (body == NULL)
    150 		return;
    151 
    152 	body_len = get_mka_param_body_len(body);
    153 	if (body->type == MKA_LIVE_PEER_LIST) {
    154 		wpa_printf(MSG_DEBUG, "*** Live Peer List ***");
    155 		wpa_printf(MSG_DEBUG, "\tBody Length...: %zu", body_len);
    156 	} else if (body->type == MKA_POTENTIAL_PEER_LIST) {
    157 		wpa_printf(MSG_DEBUG, "*** Potential Live Peer List ***");
    158 		wpa_printf(MSG_DEBUG, "\tBody Length...: %zu", body_len);
    159 	}
    160 
    161 	for (i = 0; i < body_len; i += MI_LEN + sizeof(mn)) {
    162 		mi = body->peer + i;
    163 		os_memcpy(&mn, mi + MI_LEN, sizeof(mn));
    164 		wpa_hexdump_ascii(MSG_DEBUG, "\tMember Id.....:", mi, MI_LEN);
    165 		wpa_printf(MSG_DEBUG, "\tMessage Number: %d", be_to_host32(mn));
    166 	}
    167 }
    168 
    169 
    170 /**
    171  * ieee802_1x_mka_dump_dist_sak_body -
    172  */
    173 static void
    174 ieee802_1x_mka_dump_dist_sak_body(struct ieee802_1x_mka_dist_sak_body *body)
    175 {
    176 	size_t body_len;
    177 
    178 	if (body == NULL)
    179 		return;
    180 
    181 	body_len = get_mka_param_body_len(body);
    182 	wpa_printf(MSG_INFO, "*** Distributed SAK ***");
    183 	wpa_printf(MSG_INFO, "\tDistributed AN........: %d", body->dan);
    184 	wpa_printf(MSG_INFO, "\tConfidentiality Offset: %d",
    185 		   body->confid_offset);
    186 	wpa_printf(MSG_INFO, "\tBody Length...........: %zu", body_len);
    187 	if (!body_len)
    188 		return;
    189 
    190 	wpa_printf(MSG_INFO, "\tKey Number............: %d",
    191 		   be_to_host32(body->kn));
    192 	wpa_hexdump(MSG_INFO, "\tAES Key Wrap of SAK...:", body->sak, 24);
    193 }
    194 
    195 
    196 static const char * yes_no(int val)
    197 {
    198 	return val ? "Yes" : "No";
    199 }
    200 
    201 
    202 /**
    203  * ieee802_1x_mka_dump_sak_use_body -
    204  */
    205 static void
    206 ieee802_1x_mka_dump_sak_use_body(struct ieee802_1x_mka_sak_use_body *body)
    207 {
    208 	int body_len;
    209 
    210 	if (body == NULL)
    211 		return;
    212 
    213 	body_len = get_mka_param_body_len(body);
    214 	wpa_printf(MSG_DEBUG, "*** MACsec SAK Use ***");
    215 	wpa_printf(MSG_DEBUG, "\tLatest Key AN....: %d", body->lan);
    216 	wpa_printf(MSG_DEBUG, "\tLatest Key Tx....: %s", yes_no(body->ltx));
    217 	wpa_printf(MSG_DEBUG, "\tLatest Key Rx....: %s", yes_no(body->lrx));
    218 	wpa_printf(MSG_DEBUG, "\tOld Key AN....: %d", body->oan);
    219 	wpa_printf(MSG_DEBUG, "\tOld Key Tx....: %s", yes_no(body->otx));
    220 	wpa_printf(MSG_DEBUG, "\tOld Key Rx....: %s", yes_no(body->orx));
    221 	wpa_printf(MSG_DEBUG, "\tPlain Key Tx....: %s", yes_no(body->ptx));
    222 	wpa_printf(MSG_DEBUG, "\tPlain Key Rx....: %s", yes_no(body->prx));
    223 	wpa_printf(MSG_DEBUG, "\tDelay Protect....: %s",
    224 		   yes_no(body->delay_protect));
    225 	wpa_printf(MSG_DEBUG, "\tBody Length......: %d", body_len);
    226 	if (!body_len)
    227 		return;
    228 
    229 	wpa_hexdump(MSG_DEBUG, "\tKey Server MI....:",
    230 		    body->lsrv_mi, sizeof(body->lsrv_mi));
    231 	wpa_printf(MSG_DEBUG, "\tKey Number.......: %u",
    232 		   be_to_host32(body->lkn));
    233 	wpa_printf(MSG_DEBUG, "\tLowest PN........: %u",
    234 		   be_to_host32(body->llpn));
    235 	wpa_hexdump_ascii(MSG_DEBUG, "\tOld Key Server MI....:",
    236 			  body->osrv_mi, sizeof(body->osrv_mi));
    237 	wpa_printf(MSG_DEBUG, "\tOld Key Number.......: %u",
    238 		   be_to_host32(body->okn));
    239 	wpa_printf(MSG_DEBUG, "\tOld Lowest PN........: %u",
    240 		   be_to_host32(body->olpn));
    241 }
    242 
    243 
    244 /**
    245  * ieee802_1x_kay_get_participant -
    246  */
    247 static struct ieee802_1x_mka_participant *
    248 ieee802_1x_kay_get_participant(struct ieee802_1x_kay *kay, const u8 *ckn)
    249 {
    250 	struct ieee802_1x_mka_participant *participant;
    251 
    252 	dl_list_for_each(participant, &kay->participant_list,
    253 			 struct ieee802_1x_mka_participant, list) {
    254 		if (os_memcmp(participant->ckn.name, ckn,
    255 			      participant->ckn.len) == 0)
    256 			return participant;
    257 	}
    258 
    259 	wpa_printf(MSG_DEBUG, "KaY: participant is not found");
    260 
    261 	return NULL;
    262 }
    263 
    264 
    265 /**
    266  * ieee802_1x_kay_get_principal_participant -
    267  */
    268 static struct ieee802_1x_mka_participant *
    269 ieee802_1x_kay_get_principal_participant(struct ieee802_1x_kay *kay)
    270 {
    271 	struct ieee802_1x_mka_participant *participant;
    272 
    273 	dl_list_for_each(participant, &kay->participant_list,
    274 			 struct ieee802_1x_mka_participant, list) {
    275 		if (participant->principal)
    276 			return participant;
    277 	}
    278 
    279 	wpa_printf(MSG_DEBUG, "KaY: principal participant is not found");
    280 	return NULL;
    281 }
    282 
    283 
    284 static struct ieee802_1x_kay_peer * get_peer_mi(struct dl_list *peers,
    285 						const u8 *mi)
    286 {
    287 	struct ieee802_1x_kay_peer *peer;
    288 
    289 	dl_list_for_each(peer, peers, struct ieee802_1x_kay_peer, list) {
    290 		if (os_memcmp(peer->mi, mi, MI_LEN) == 0)
    291 			return peer;
    292 	}
    293 
    294 	return NULL;
    295 }
    296 
    297 
    298 /**
    299  * ieee802_1x_kay_get_potential_peer
    300  */
    301 static struct ieee802_1x_kay_peer *
    302 ieee802_1x_kay_get_potential_peer(
    303 	struct ieee802_1x_mka_participant *participant, const u8 *mi)
    304 {
    305 	return get_peer_mi(&participant->potential_peers, mi);
    306 }
    307 
    308 
    309 /**
    310  * ieee802_1x_kay_get_live_peer
    311  */
    312 static struct ieee802_1x_kay_peer *
    313 ieee802_1x_kay_get_live_peer(struct ieee802_1x_mka_participant *participant,
    314 			     const u8 *mi)
    315 {
    316 	return get_peer_mi(&participant->live_peers, mi);
    317 }
    318 
    319 
    320 /**
    321  * ieee802_1x_kay_is_in_potential_peer
    322  */
    323 static Boolean
    324 ieee802_1x_kay_is_in_potential_peer(
    325 	struct ieee802_1x_mka_participant *participant, const u8 *mi)
    326 {
    327 	return ieee802_1x_kay_get_potential_peer(participant, mi) != NULL;
    328 }
    329 
    330 
    331 /**
    332  * ieee802_1x_kay_is_in_live_peer
    333  */
    334 static Boolean
    335 ieee802_1x_kay_is_in_live_peer(
    336 	struct ieee802_1x_mka_participant *participant, const u8 *mi)
    337 {
    338 	return ieee802_1x_kay_get_live_peer(participant, mi) != NULL;
    339 }
    340 
    341 
    342 /**
    343  * ieee802_1x_kay_get_peer
    344  */
    345 static struct ieee802_1x_kay_peer *
    346 ieee802_1x_kay_get_peer(struct ieee802_1x_mka_participant *participant,
    347 			const u8 *mi)
    348 {
    349 	struct ieee802_1x_kay_peer *peer;
    350 
    351 	peer = ieee802_1x_kay_get_live_peer(participant, mi);
    352 	if (peer)
    353 		return peer;
    354 
    355 	return ieee802_1x_kay_get_potential_peer(participant, mi);
    356 }
    357 
    358 
    359 /**
    360  * ieee802_1x_kay_get_cipher_suite
    361  */
    362 static struct macsec_ciphersuite *
    363 ieee802_1x_kay_get_cipher_suite(struct ieee802_1x_mka_participant *participant,
    364 				const u8 *cs_id)
    365 {
    366 	unsigned int i;
    367 	u64 cs;
    368 	be64 _cs;
    369 
    370 	os_memcpy(&_cs, cs_id, CS_ID_LEN);
    371 	cs = be_to_host64(_cs);
    372 
    373 	for (i = 0; i < CS_TABLE_SIZE; i++) {
    374 		if (cipher_suite_tbl[i].id == cs)
    375 			return &cipher_suite_tbl[i];
    376 	}
    377 
    378 	return NULL;
    379 }
    380 
    381 
    382 u64 mka_sci_u64(struct ieee802_1x_mka_sci *sci)
    383 {
    384 	struct ieee802_1x_mka_sci tmp;
    385 
    386 	os_memcpy(tmp.addr, sci->addr, ETH_ALEN);
    387 	tmp.port = sci->port;
    388 
    389 	return *((u64 *) &tmp);
    390 }
    391 
    392 
    393 static Boolean sci_equal(const struct ieee802_1x_mka_sci *a,
    394 			 const struct ieee802_1x_mka_sci *b)
    395 {
    396 	return os_memcmp(a, b, sizeof(struct ieee802_1x_mka_sci)) == 0;
    397 }
    398 
    399 
    400 /**
    401  * ieee802_1x_kay_get_peer_sci
    402  */
    403 static struct ieee802_1x_kay_peer *
    404 ieee802_1x_kay_get_peer_sci(struct ieee802_1x_mka_participant *participant,
    405 			    const struct ieee802_1x_mka_sci *sci)
    406 {
    407 	struct ieee802_1x_kay_peer *peer;
    408 
    409 	dl_list_for_each(peer, &participant->live_peers,
    410 			 struct ieee802_1x_kay_peer, list) {
    411 		if (sci_equal(&peer->sci, sci))
    412 			return peer;
    413 	}
    414 
    415 	dl_list_for_each(peer, &participant->potential_peers,
    416 			 struct ieee802_1x_kay_peer, list) {
    417 		if (sci_equal(&peer->sci, sci))
    418 			return peer;
    419 	}
    420 
    421 	return NULL;
    422 }
    423 
    424 
    425 static void ieee802_1x_kay_use_data_key(struct data_key *pkey);
    426 
    427 /**
    428  * ieee802_1x_kay_init_receive_sa -
    429  */
    430 static struct receive_sa *
    431 ieee802_1x_kay_init_receive_sa(struct receive_sc *psc, u8 an, u32 lowest_pn,
    432 			       struct data_key *key)
    433 {
    434 	struct receive_sa *psa;
    435 
    436 	if (!psc || !key)
    437 		return NULL;
    438 
    439 	psa = os_zalloc(sizeof(*psa));
    440 	if (!psa) {
    441 		wpa_printf(MSG_ERROR, "%s: out of memory", __func__);
    442 		return NULL;
    443 	}
    444 
    445 	ieee802_1x_kay_use_data_key(key);
    446 	psa->pkey = key;
    447 	psa->lowest_pn = lowest_pn;
    448 	psa->next_pn = lowest_pn;
    449 	psa->an = an;
    450 	psa->sc = psc;
    451 
    452 	os_get_time(&psa->created_time);
    453 	psa->in_use = FALSE;
    454 
    455 	dl_list_add(&psc->sa_list, &psa->list);
    456 	wpa_printf(MSG_DEBUG,
    457 		   "KaY: Create receive SA(AN: %hhu lowest_pn: %u of SC",
    458 		   an, lowest_pn);
    459 
    460 	return psa;
    461 }
    462 
    463 
    464 static void ieee802_1x_kay_deinit_data_key(struct data_key *pkey);
    465 
    466 /**
    467  * ieee802_1x_kay_deinit_receive_sa -
    468  */
    469 static void ieee802_1x_kay_deinit_receive_sa(struct receive_sa *psa)
    470 {
    471 	ieee802_1x_kay_deinit_data_key(psa->pkey);
    472 	psa->pkey = NULL;
    473 	wpa_printf(MSG_DEBUG,
    474 		   "KaY: Delete receive SA(an: %hhu) of SC",
    475 		   psa->an);
    476 	dl_list_del(&psa->list);
    477 	os_free(psa);
    478 }
    479 
    480 
    481 /**
    482  * ieee802_1x_kay_init_receive_sc -
    483  */
    484 static struct receive_sc *
    485 ieee802_1x_kay_init_receive_sc(const struct ieee802_1x_mka_sci *psci)
    486 {
    487 	struct receive_sc *psc;
    488 
    489 	if (!psci)
    490 		return NULL;
    491 
    492 	psc = os_zalloc(sizeof(*psc));
    493 	if (!psc) {
    494 		wpa_printf(MSG_ERROR, "%s: out of memory", __func__);
    495 		return NULL;
    496 	}
    497 
    498 	os_memcpy(&psc->sci, psci, sizeof(psc->sci));
    499 
    500 	os_get_time(&psc->created_time);
    501 	psc->receiving = FALSE;
    502 
    503 	dl_list_init(&psc->sa_list);
    504 	wpa_printf(MSG_DEBUG, "KaY: Create receive SC");
    505 	wpa_hexdump(MSG_DEBUG, "SCI: ", (u8 *)psci, sizeof(*psci));
    506 
    507 	return psc;
    508 }
    509 
    510 
    511 static void ieee802_1x_delete_receive_sa(struct ieee802_1x_kay *kay,
    512 					 struct receive_sa *sa)
    513 {
    514 	secy_disable_receive_sa(kay, sa);
    515 	secy_delete_receive_sa(kay, sa);
    516 	ieee802_1x_kay_deinit_receive_sa(sa);
    517 }
    518 
    519 
    520 /**
    521  * ieee802_1x_kay_deinit_receive_sc -
    522  **/
    523 static void
    524 ieee802_1x_kay_deinit_receive_sc(
    525 	struct ieee802_1x_mka_participant *participant, struct receive_sc *psc)
    526 {
    527 	struct receive_sa *psa, *pre_sa;
    528 
    529 	wpa_printf(MSG_DEBUG, "KaY: Delete receive SC");
    530 	dl_list_for_each_safe(psa, pre_sa, &psc->sa_list, struct receive_sa,
    531 			      list)
    532 		ieee802_1x_delete_receive_sa(participant->kay, psa);
    533 
    534 	dl_list_del(&psc->list);
    535 	os_free(psc);
    536 }
    537 
    538 
    539 static void ieee802_1x_kay_dump_peer(struct ieee802_1x_kay_peer *peer)
    540 {
    541 	wpa_hexdump(MSG_DEBUG, "\tMI: ", peer->mi, sizeof(peer->mi));
    542 	wpa_printf(MSG_DEBUG, "\tMN: %d", peer->mn);
    543 	wpa_hexdump(MSG_DEBUG, "\tSCI Addr: ", peer->sci.addr, ETH_ALEN);
    544 	wpa_printf(MSG_DEBUG, "\tPort: %d", peer->sci.port);
    545 }
    546 
    547 
    548 static struct ieee802_1x_kay_peer *
    549 ieee802_1x_kay_create_peer(const u8 *mi, u32 mn)
    550 {
    551 	struct ieee802_1x_kay_peer *peer;
    552 
    553 	peer = os_zalloc(sizeof(*peer));
    554 	if (!peer) {
    555 		wpa_printf(MSG_ERROR, "KaY-%s: out of memory", __func__);
    556 		return NULL;
    557 	}
    558 
    559 	os_memcpy(peer->mi, mi, MI_LEN);
    560 	peer->mn = mn;
    561 	peer->expire = time(NULL) + MKA_LIFE_TIME / 1000;
    562 	peer->sak_used = FALSE;
    563 
    564 	return peer;
    565 }
    566 
    567 
    568 /**
    569  * ieee802_1x_kay_create_live_peer
    570  */
    571 static struct ieee802_1x_kay_peer *
    572 ieee802_1x_kay_create_live_peer(struct ieee802_1x_mka_participant *participant,
    573 				const u8 *mi, u32 mn)
    574 {
    575 	struct ieee802_1x_kay_peer *peer;
    576 	struct receive_sc *rxsc;
    577 
    578 	peer = ieee802_1x_kay_create_peer(mi, mn);
    579 	if (!peer)
    580 		return NULL;
    581 
    582 	os_memcpy(&peer->sci, &participant->current_peer_sci,
    583 		  sizeof(peer->sci));
    584 
    585 	rxsc = ieee802_1x_kay_init_receive_sc(&peer->sci);
    586 	if (!rxsc) {
    587 		os_free(peer);
    588 		return NULL;
    589 	}
    590 
    591 	dl_list_add(&participant->live_peers, &peer->list);
    592 	dl_list_add(&participant->rxsc_list, &rxsc->list);
    593 	secy_create_receive_sc(participant->kay, rxsc);
    594 
    595 	wpa_printf(MSG_DEBUG, "KaY: Live peer created");
    596 	ieee802_1x_kay_dump_peer(peer);
    597 
    598 	return peer;
    599 }
    600 
    601 
    602 /**
    603  * ieee802_1x_kay_create_potential_peer
    604  */
    605 static struct ieee802_1x_kay_peer *
    606 ieee802_1x_kay_create_potential_peer(
    607 	struct ieee802_1x_mka_participant *participant, const u8 *mi, u32 mn)
    608 {
    609 	struct ieee802_1x_kay_peer *peer;
    610 
    611 	peer = ieee802_1x_kay_create_peer(mi, mn);
    612 	if (!peer)
    613 		return NULL;
    614 
    615 	dl_list_add(&participant->potential_peers, &peer->list);
    616 
    617 	wpa_printf(MSG_DEBUG, "KaY: potential peer created");
    618 	ieee802_1x_kay_dump_peer(peer);
    619 
    620 	return peer;
    621 }
    622 
    623 
    624 /**
    625  * ieee802_1x_kay_move_live_peer
    626  */
    627 static struct ieee802_1x_kay_peer *
    628 ieee802_1x_kay_move_live_peer(struct ieee802_1x_mka_participant *participant,
    629 			      u8 *mi, u32 mn)
    630 {
    631 	struct ieee802_1x_kay_peer *peer;
    632 	struct receive_sc *rxsc;
    633 
    634 	peer = ieee802_1x_kay_get_potential_peer(participant, mi);
    635 
    636 	rxsc = ieee802_1x_kay_init_receive_sc(&participant->current_peer_sci);
    637 	if (!rxsc)
    638 		return NULL;
    639 
    640 	os_memcpy(&peer->sci, &participant->current_peer_sci,
    641 		  sizeof(peer->sci));
    642 	peer->mn = mn;
    643 	peer->expire = time(NULL) + MKA_LIFE_TIME / 1000;
    644 
    645 	wpa_printf(MSG_DEBUG, "KaY: move potential peer to live peer");
    646 	ieee802_1x_kay_dump_peer(peer);
    647 
    648 	dl_list_del(&peer->list);
    649 	dl_list_add_tail(&participant->live_peers, &peer->list);
    650 
    651 	dl_list_add(&participant->rxsc_list, &rxsc->list);
    652 	secy_create_receive_sc(participant->kay, rxsc);
    653 
    654 	return peer;
    655 }
    656 
    657 
    658 
    659 /**
    660  *  ieee802_1x_mka_basic_body_present -
    661  */
    662 static Boolean
    663 ieee802_1x_mka_basic_body_present(
    664 	struct ieee802_1x_mka_participant *participant)
    665 {
    666 	return TRUE;
    667 }
    668 
    669 
    670 /**
    671  * ieee802_1x_mka_basic_body_length -
    672  */
    673 static int
    674 ieee802_1x_mka_basic_body_length(struct ieee802_1x_mka_participant *participant)
    675 {
    676 	int length;
    677 
    678 	length = sizeof(struct ieee802_1x_mka_basic_body);
    679 	length += participant->ckn.len;
    680 	return MKA_ALIGN_LENGTH(length);
    681 }
    682 
    683 
    684 /**
    685  * ieee802_1x_mka_encode_basic_body
    686  */
    687 static int
    688 ieee802_1x_mka_encode_basic_body(
    689 	struct ieee802_1x_mka_participant *participant,
    690 	struct wpabuf *buf)
    691 {
    692 	struct ieee802_1x_mka_basic_body *body;
    693 	struct ieee802_1x_kay *kay = participant->kay;
    694 	unsigned int length = ieee802_1x_mka_basic_body_length(participant);
    695 
    696 	body = wpabuf_put(buf, length);
    697 
    698 	body->version = kay->mka_version;
    699 	body->priority = kay->actor_priority;
    700 	if (participant->is_elected)
    701 		body->key_server = participant->is_key_server;
    702 	else
    703 		body->key_server = participant->can_be_key_server;
    704 
    705 	body->macsec_desired = kay->macsec_desired;
    706 	body->macsec_capability = kay->macsec_capable;
    707 	set_mka_param_body_len(body, length - MKA_HDR_LEN);
    708 
    709 	os_memcpy(body->actor_sci.addr, kay->actor_sci.addr,
    710 		  sizeof(kay->actor_sci.addr));
    711 	body->actor_sci.port = kay->actor_sci.port;
    712 
    713 	os_memcpy(body->actor_mi, participant->mi, sizeof(body->actor_mi));
    714 	participant->mn = participant->mn + 1;
    715 	body->actor_mn = host_to_be32(participant->mn);
    716 	os_memcpy(body->algo_agility, kay->algo_agility,
    717 		  sizeof(body->algo_agility));
    718 
    719 	os_memcpy(body->ckn, participant->ckn.name, participant->ckn.len);
    720 
    721 	ieee802_1x_mka_dump_basic_body(body);
    722 
    723 	return 0;
    724 }
    725 
    726 
    727 static Boolean
    728 reset_participant_mi(struct ieee802_1x_mka_participant *participant)
    729 {
    730 	if (os_get_random(participant->mi, sizeof(participant->mi)) < 0)
    731 		return FALSE;
    732 	participant->mn = 0;
    733 
    734 	return TRUE;
    735 }
    736 
    737 
    738 /**
    739  * ieee802_1x_mka_decode_basic_body -
    740  */
    741 static struct ieee802_1x_mka_participant *
    742 ieee802_1x_mka_decode_basic_body(struct ieee802_1x_kay *kay, const u8 *mka_msg,
    743 				 size_t msg_len)
    744 {
    745 	struct ieee802_1x_mka_participant *participant;
    746 	const struct ieee802_1x_mka_basic_body *body;
    747 	struct ieee802_1x_kay_peer *peer;
    748 
    749 	body = (const struct ieee802_1x_mka_basic_body *) mka_msg;
    750 
    751 	if (body->version > MKA_VERSION_ID) {
    752 		wpa_printf(MSG_DEBUG,
    753 			   "KaY: peer's version(%d) greater than mka current version(%d)",
    754 			   body->version, MKA_VERSION_ID);
    755 	}
    756 	if (kay->is_obliged_key_server && body->key_server) {
    757 		wpa_printf(MSG_DEBUG, "I must be as key server");
    758 		return NULL;
    759 	}
    760 
    761 	participant = ieee802_1x_kay_get_participant(kay, body->ckn);
    762 	if (!participant) {
    763 		wpa_printf(MSG_DEBUG, "Peer is not included in my CA");
    764 		return NULL;
    765 	}
    766 
    767 	/* If the peer's MI is my MI, I will choose new MI */
    768 	if (os_memcmp(body->actor_mi, participant->mi, MI_LEN) == 0) {
    769 		if (!reset_participant_mi(participant))
    770 			return NULL;
    771 	}
    772 
    773 	os_memcpy(participant->current_peer_id.mi, body->actor_mi, MI_LEN);
    774 	participant->current_peer_id.mn = body->actor_mn;
    775 	os_memcpy(participant->current_peer_sci.addr, body->actor_sci.addr,
    776 		  sizeof(participant->current_peer_sci.addr));
    777 	participant->current_peer_sci.port = body->actor_sci.port;
    778 
    779 	/* handler peer */
    780 	peer = ieee802_1x_kay_get_peer(participant, body->actor_mi);
    781 	if (!peer) {
    782 		/* Check duplicated SCI */
    783 		/* TODO: What policy should be applied to detect duplicated SCI
    784 		 * is active attacker or a valid peer whose MI is be changed?
    785 		 */
    786 		peer = ieee802_1x_kay_get_peer_sci(participant,
    787 						   &body->actor_sci);
    788 		if (peer) {
    789 			wpa_printf(MSG_WARNING,
    790 				   "KaY: duplicated SCI detected, Maybe active attacker");
    791 			dl_list_del(&peer->list);
    792 			os_free(peer);
    793 		}
    794 
    795 		peer = ieee802_1x_kay_create_potential_peer(
    796 			participant, body->actor_mi,
    797 			be_to_host32(body->actor_mn));
    798 		if (!peer)
    799 			return NULL;
    800 
    801 		peer->macsec_desired = body->macsec_desired;
    802 		peer->macsec_capability = body->macsec_capability;
    803 		peer->is_key_server = (Boolean) body->key_server;
    804 		peer->key_server_priority = body->priority;
    805 	} else if (peer->mn < be_to_host32(body->actor_mn)) {
    806 		peer->mn = be_to_host32(body->actor_mn);
    807 		peer->expire = time(NULL) + MKA_LIFE_TIME / 1000;
    808 		peer->macsec_desired = body->macsec_desired;
    809 		peer->macsec_capability = body->macsec_capability;
    810 		peer->is_key_server = (Boolean) body->key_server;
    811 		peer->key_server_priority = body->priority;
    812 	} else {
    813 		wpa_printf(MSG_WARNING, "KaY: The peer MN have received");
    814 		return NULL;
    815 	}
    816 
    817 	return participant;
    818 }
    819 
    820 
    821 /**
    822  * ieee802_1x_mka_live_peer_body_present
    823  */
    824 static Boolean
    825 ieee802_1x_mka_live_peer_body_present(
    826 	struct ieee802_1x_mka_participant *participant)
    827 {
    828 	return !dl_list_empty(&participant->live_peers);
    829 }
    830 
    831 
    832 /**
    833  * ieee802_1x_kay_get_live_peer_length
    834  */
    835 static int
    836 ieee802_1x_mka_get_live_peer_length(
    837 	struct ieee802_1x_mka_participant *participant)
    838 {
    839 	int len = MKA_HDR_LEN;
    840 	struct ieee802_1x_kay_peer *peer;
    841 
    842 	dl_list_for_each(peer, &participant->live_peers,
    843 			 struct ieee802_1x_kay_peer, list)
    844 		len += sizeof(struct ieee802_1x_mka_peer_id);
    845 
    846 	return MKA_ALIGN_LENGTH(len);
    847 }
    848 
    849 
    850 /**
    851  * ieee802_1x_mka_encode_live_peer_body -
    852  */
    853 static int
    854 ieee802_1x_mka_encode_live_peer_body(
    855 	struct ieee802_1x_mka_participant *participant,
    856 	struct wpabuf *buf)
    857 {
    858 	struct ieee802_1x_mka_peer_body *body;
    859 	struct ieee802_1x_kay_peer *peer;
    860 	unsigned int length;
    861 	struct ieee802_1x_mka_peer_id *body_peer;
    862 
    863 	length = ieee802_1x_mka_get_live_peer_length(participant);
    864 	body = wpabuf_put(buf, sizeof(struct ieee802_1x_mka_peer_body));
    865 
    866 	body->type = MKA_LIVE_PEER_LIST;
    867 	set_mka_param_body_len(body, length - MKA_HDR_LEN);
    868 
    869 	dl_list_for_each(peer, &participant->live_peers,
    870 			 struct ieee802_1x_kay_peer, list) {
    871 		body_peer = wpabuf_put(buf,
    872 				       sizeof(struct ieee802_1x_mka_peer_id));
    873 		os_memcpy(body_peer->mi, peer->mi, MI_LEN);
    874 		body_peer->mn = host_to_be32(peer->mn);
    875 	}
    876 
    877 	ieee802_1x_mka_dump_peer_body(body);
    878 	return 0;
    879 }
    880 
    881 /**
    882  * ieee802_1x_mka_potential_peer_body_present
    883  */
    884 static Boolean
    885 ieee802_1x_mka_potential_peer_body_present(
    886 	struct ieee802_1x_mka_participant *participant)
    887 {
    888 	return !dl_list_empty(&participant->potential_peers);
    889 }
    890 
    891 
    892 /**
    893  * ieee802_1x_kay_get_potential_peer_length
    894  */
    895 static int
    896 ieee802_1x_mka_get_potential_peer_length(
    897 	struct ieee802_1x_mka_participant *participant)
    898 {
    899 	int len = MKA_HDR_LEN;
    900 	struct ieee802_1x_kay_peer *peer;
    901 
    902 	dl_list_for_each(peer, &participant->potential_peers,
    903 			 struct ieee802_1x_kay_peer, list)
    904 		len += sizeof(struct ieee802_1x_mka_peer_id);
    905 
    906 	return MKA_ALIGN_LENGTH(len);
    907 }
    908 
    909 
    910 /**
    911  * ieee802_1x_mka_encode_potential_peer_body -
    912  */
    913 static int
    914 ieee802_1x_mka_encode_potential_peer_body(
    915 	struct ieee802_1x_mka_participant *participant,
    916 	struct wpabuf *buf)
    917 {
    918 	struct ieee802_1x_mka_peer_body *body;
    919 	struct ieee802_1x_kay_peer *peer;
    920 	unsigned int length;
    921 	struct ieee802_1x_mka_peer_id *body_peer;
    922 
    923 	length = ieee802_1x_mka_get_potential_peer_length(participant);
    924 	body = wpabuf_put(buf, sizeof(struct ieee802_1x_mka_peer_body));
    925 
    926 	body->type = MKA_POTENTIAL_PEER_LIST;
    927 	set_mka_param_body_len(body, length - MKA_HDR_LEN);
    928 
    929 	dl_list_for_each(peer, &participant->potential_peers,
    930 			 struct ieee802_1x_kay_peer, list) {
    931 		body_peer = wpabuf_put(buf,
    932 				       sizeof(struct ieee802_1x_mka_peer_id));
    933 		os_memcpy(body_peer->mi, peer->mi, MI_LEN);
    934 		body_peer->mn = host_to_be32(peer->mn);
    935 	}
    936 
    937 	ieee802_1x_mka_dump_peer_body(body);
    938 	return 0;
    939 }
    940 
    941 
    942 /**
    943  * ieee802_1x_mka_i_in_peerlist -
    944  */
    945 static Boolean
    946 ieee802_1x_mka_i_in_peerlist(struct ieee802_1x_mka_participant *participant,
    947 			     const u8 *mka_msg, size_t msg_len)
    948 {
    949 	struct ieee802_1x_mka_hdr *hdr;
    950 	size_t body_len;
    951 	size_t left_len;
    952 	u8 body_type;
    953 	const u8 *pos;
    954 	size_t i;
    955 
    956 	for (pos = mka_msg, left_len = msg_len;
    957 	     left_len > MKA_HDR_LEN + DEFAULT_ICV_LEN;
    958 	     left_len -= body_len + MKA_HDR_LEN,
    959 		     pos += body_len + MKA_HDR_LEN) {
    960 		hdr = (struct ieee802_1x_mka_hdr *) pos;
    961 		body_len = get_mka_param_body_len(hdr);
    962 		body_type = get_mka_param_body_type(hdr);
    963 
    964 		if (body_type != MKA_LIVE_PEER_LIST &&
    965 		    body_type != MKA_POTENTIAL_PEER_LIST)
    966 			continue;
    967 
    968 		ieee802_1x_mka_dump_peer_body(
    969 			(struct ieee802_1x_mka_peer_body *)pos);
    970 
    971 		if (left_len < (MKA_HDR_LEN + body_len + DEFAULT_ICV_LEN)) {
    972 			wpa_printf(MSG_ERROR,
    973 				   "KaY: MKA Peer Packet Body Length (%zu bytes) is less than the Parameter Set Header Length (%zu bytes) + the Parameter Set Body Length (%zu bytes) + %d bytes of ICV",
    974 				   left_len, MKA_HDR_LEN,
    975 				   body_len, DEFAULT_ICV_LEN);
    976 			continue;
    977 		}
    978 
    979 		if ((body_len % 16) != 0) {
    980 			wpa_printf(MSG_ERROR,
    981 				   "KaY: MKA Peer Packet Body Length (%zu bytes) should be a multiple of 16 octets",
    982 				   body_len);
    983 			continue;
    984 		}
    985 
    986 		for (i = 0; i < body_len;
    987 		     i += sizeof(struct ieee802_1x_mka_peer_id)) {
    988 			const struct ieee802_1x_mka_peer_id *peer_mi;
    989 
    990 			peer_mi = (const struct ieee802_1x_mka_peer_id *)
    991 				(pos + MKA_HDR_LEN + i);
    992 			if (os_memcmp(peer_mi->mi, participant->mi,
    993 				      MI_LEN) == 0 &&
    994 			    be_to_host32(peer_mi->mn) == participant->mn)
    995 				return TRUE;
    996 		}
    997 	}
    998 
    999 	return FALSE;
   1000 }
   1001 
   1002 
   1003 /**
   1004  * ieee802_1x_mka_decode_live_peer_body -
   1005  */
   1006 static int ieee802_1x_mka_decode_live_peer_body(
   1007 	struct ieee802_1x_mka_participant *participant,
   1008 	const u8 *peer_msg, size_t msg_len)
   1009 {
   1010 	const struct ieee802_1x_mka_hdr *hdr;
   1011 	struct ieee802_1x_kay_peer *peer;
   1012 	size_t body_len;
   1013 	size_t i;
   1014 	Boolean is_included;
   1015 
   1016 	is_included = ieee802_1x_kay_is_in_live_peer(
   1017 		participant, participant->current_peer_id.mi);
   1018 
   1019 	hdr = (const struct ieee802_1x_mka_hdr *) peer_msg;
   1020 	body_len = get_mka_param_body_len(hdr);
   1021 	if (body_len % 16 != 0) {
   1022 		wpa_printf(MSG_ERROR,
   1023 			   "KaY: MKA Peer Packet Body Length (%zu bytes) should be a multiple of 16 octets",
   1024 			   body_len);
   1025 		return -1;
   1026 	}
   1027 
   1028 	for (i = 0; i < body_len; i += sizeof(struct ieee802_1x_mka_peer_id)) {
   1029 		const struct ieee802_1x_mka_peer_id *peer_mi;
   1030 		u32 peer_mn;
   1031 
   1032 		peer_mi = (const struct ieee802_1x_mka_peer_id *)
   1033 			(peer_msg + MKA_HDR_LEN + i);
   1034 		peer_mn = be_to_host32(peer_mi->mn);
   1035 
   1036 		/* it is myself */
   1037 		if (os_memcmp(peer_mi, participant->mi, MI_LEN) == 0) {
   1038 			/* My message id is used by other participant */
   1039 			if (peer_mn > participant->mn &&
   1040 			    !reset_participant_mi(participant))
   1041 				wpa_printf(MSG_DEBUG, "KaY: Could not update mi");
   1042 			continue;
   1043 		}
   1044 
   1045 		if (!is_included)
   1046 			continue;
   1047 
   1048 		peer = ieee802_1x_kay_get_peer(participant, peer_mi->mi);
   1049 		if (peer) {
   1050 			peer->mn = peer_mn;
   1051 			peer->expire = time(NULL) + MKA_LIFE_TIME / 1000;
   1052 		} else if (!ieee802_1x_kay_create_potential_peer(
   1053 				participant, peer_mi->mi, peer_mn)) {
   1054 			return -1;
   1055 		}
   1056 	}
   1057 
   1058 	return 0;
   1059 }
   1060 
   1061 
   1062 /**
   1063  * ieee802_1x_mka_decode_potential_peer_body -
   1064  */
   1065 static int
   1066 ieee802_1x_mka_decode_potential_peer_body(
   1067 	struct ieee802_1x_mka_participant *participant,
   1068 	const u8 *peer_msg, size_t msg_len)
   1069 {
   1070 	const struct ieee802_1x_mka_hdr *hdr;
   1071 	size_t body_len;
   1072 	size_t i;
   1073 
   1074 	hdr = (const struct ieee802_1x_mka_hdr *) peer_msg;
   1075 	body_len = get_mka_param_body_len(hdr);
   1076 	if (body_len % 16 != 0) {
   1077 		wpa_printf(MSG_ERROR,
   1078 			   "KaY: MKA Peer Packet Body Length (%zu bytes) should be a multiple of 16 octets",
   1079 			   body_len);
   1080 		return -1;
   1081 	}
   1082 
   1083 	for (i = 0; i < body_len; i += sizeof(struct ieee802_1x_mka_peer_id)) {
   1084 		const struct ieee802_1x_mka_peer_id *peer_mi;
   1085 		u32 peer_mn;
   1086 
   1087 		peer_mi = (struct ieee802_1x_mka_peer_id *)
   1088 			(peer_msg + MKA_HDR_LEN + i);
   1089 		peer_mn = be_to_host32(peer_mi->mn);
   1090 
   1091 		/* it is myself */
   1092 		if (os_memcmp(peer_mi, participant->mi, MI_LEN) == 0) {
   1093 			/* My message id is used by other participant */
   1094 			if (peer_mn > participant->mn &&
   1095 			    !reset_participant_mi(participant))
   1096 				wpa_printf(MSG_DEBUG, "KaY: Could not update mi");
   1097 			continue;
   1098 		}
   1099 	}
   1100 
   1101 	return 0;
   1102 }
   1103 
   1104 
   1105 /**
   1106  * ieee802_1x_mka_sak_use_body_present
   1107  */
   1108 static Boolean
   1109 ieee802_1x_mka_sak_use_body_present(
   1110 	struct ieee802_1x_mka_participant *participant)
   1111 {
   1112 	return participant->to_use_sak;
   1113 }
   1114 
   1115 
   1116 /**
   1117  * ieee802_1x_mka_get_sak_use_length
   1118  */
   1119 static int
   1120 ieee802_1x_mka_get_sak_use_length(
   1121 	struct ieee802_1x_mka_participant *participant)
   1122 {
   1123 	int length = MKA_HDR_LEN;
   1124 
   1125 	if (participant->kay->macsec_desired && participant->advised_desired)
   1126 		length = sizeof(struct ieee802_1x_mka_sak_use_body);
   1127 
   1128 	return MKA_ALIGN_LENGTH(length);
   1129 }
   1130 
   1131 
   1132 /**
   1133  *
   1134  */
   1135 static u32
   1136 ieee802_1x_mka_get_lpn(struct ieee802_1x_mka_participant *principal,
   1137 		       struct ieee802_1x_mka_ki *ki)
   1138 {
   1139 	struct receive_sa *rxsa;
   1140 	struct receive_sc *rxsc;
   1141 	u32 lpn = 0;
   1142 
   1143 	dl_list_for_each(rxsc, &principal->rxsc_list, struct receive_sc, list) {
   1144 		dl_list_for_each(rxsa, &rxsc->sa_list, struct receive_sa, list)
   1145 		{
   1146 			if (is_ki_equal(&rxsa->pkey->key_identifier, ki)) {
   1147 				secy_get_receive_lowest_pn(principal->kay,
   1148 							   rxsa);
   1149 
   1150 				lpn = lpn > rxsa->lowest_pn ?
   1151 					lpn : rxsa->lowest_pn;
   1152 				break;
   1153 			}
   1154 		}
   1155 	}
   1156 
   1157 	if (lpn == 0)
   1158 		lpn = 1;
   1159 
   1160 	return lpn;
   1161 }
   1162 
   1163 
   1164 /**
   1165  * ieee802_1x_mka_encode_sak_use_body -
   1166  */
   1167 static int
   1168 ieee802_1x_mka_encode_sak_use_body(
   1169 	struct ieee802_1x_mka_participant *participant,
   1170 	struct wpabuf *buf)
   1171 {
   1172 	struct ieee802_1x_mka_sak_use_body *body;
   1173 	struct ieee802_1x_kay *kay = participant->kay;
   1174 	unsigned int length;
   1175 	u32 pn = 1;
   1176 
   1177 	length = ieee802_1x_mka_get_sak_use_length(participant);
   1178 	body = wpabuf_put(buf, length);
   1179 
   1180 	body->type = MKA_SAK_USE;
   1181 	set_mka_param_body_len(body, length - MKA_HDR_LEN);
   1182 
   1183 	if (length == MKA_HDR_LEN) {
   1184 		body->ptx = TRUE;
   1185 		body->prx = TRUE;
   1186 		body->lan = 0;
   1187 		body->lrx = FALSE;
   1188 		body->ltx = FALSE;
   1189 		body->delay_protect = FALSE;
   1190 		return 0;
   1191 	}
   1192 
   1193 	/* data protect, lowest accept packet number */
   1194 	body->delay_protect = kay->macsec_replay_protect;
   1195 	pn = ieee802_1x_mka_get_lpn(participant, &participant->lki);
   1196 	if (pn > kay->pn_exhaustion) {
   1197 		wpa_printf(MSG_WARNING, "KaY: My LPN exhaustion");
   1198 		if (participant->is_key_server)
   1199 			participant->new_sak = TRUE;
   1200 	}
   1201 
   1202 	body->llpn = host_to_be32(pn);
   1203 	pn = ieee802_1x_mka_get_lpn(participant, &participant->oki);
   1204 	body->olpn = host_to_be32(pn);
   1205 
   1206 	/* plain tx, plain rx */
   1207 	body->ptx = !kay->macsec_protect;
   1208 	body->prx = kay->macsec_validate != Strict;
   1209 
   1210 	/* latest key: rx, tx, key server member identifier key number */
   1211 	body->lan = participant->lan;
   1212 	os_memcpy(body->lsrv_mi, participant->lki.mi, sizeof(body->lsrv_mi));
   1213 	body->lkn = host_to_be32(participant->lki.kn);
   1214 	body->lrx = participant->lrx;
   1215 	body->ltx = participant->ltx;
   1216 
   1217 	/* old key: rx, tx, key server member identifier key number */
   1218 	body->oan = participant->oan;
   1219 	if (participant->oki.kn != participant->lki.kn &&
   1220 	    participant->oki.kn != 0) {
   1221 		body->otx = TRUE;
   1222 		body->orx = TRUE;
   1223 		os_memcpy(body->osrv_mi, participant->oki.mi,
   1224 			  sizeof(body->osrv_mi));
   1225 		body->okn = host_to_be32(participant->oki.kn);
   1226 	} else {
   1227 		body->otx = FALSE;
   1228 		body->orx = FALSE;
   1229 	}
   1230 
   1231 	/* set CP's variable */
   1232 	if (body->ltx) {
   1233 		kay->tx_enable = TRUE;
   1234 		kay->port_enable = TRUE;
   1235 	}
   1236 	if (body->lrx)
   1237 		kay->rx_enable = TRUE;
   1238 
   1239 	ieee802_1x_mka_dump_sak_use_body(body);
   1240 	return 0;
   1241 }
   1242 
   1243 
   1244 /**
   1245  * ieee802_1x_mka_decode_sak_use_body -
   1246  */
   1247 static int
   1248 ieee802_1x_mka_decode_sak_use_body(
   1249 	struct ieee802_1x_mka_participant *participant,
   1250 	const u8 *mka_msg, size_t msg_len)
   1251 {
   1252 	struct ieee802_1x_mka_hdr *hdr;
   1253 	struct ieee802_1x_mka_sak_use_body *body;
   1254 	struct ieee802_1x_kay_peer *peer;
   1255 	struct transmit_sa *txsa;
   1256 	struct data_key *sa_key = NULL;
   1257 	size_t body_len;
   1258 	struct ieee802_1x_mka_ki ki;
   1259 	u32 lpn;
   1260 	Boolean all_receiving;
   1261 	Boolean found;
   1262 	struct ieee802_1x_kay *kay = participant->kay;
   1263 
   1264 	if (!participant->principal) {
   1265 		wpa_printf(MSG_WARNING, "KaY: Participant is not principal");
   1266 		return -1;
   1267 	}
   1268 	peer = ieee802_1x_kay_get_live_peer(participant,
   1269 					    participant->current_peer_id.mi);
   1270 	if (!peer) {
   1271 		wpa_printf(MSG_WARNING, "KaY: the peer is not my live peer");
   1272 		return -1;
   1273 	}
   1274 
   1275 	hdr = (struct ieee802_1x_mka_hdr *) mka_msg;
   1276 	body_len = get_mka_param_body_len(hdr);
   1277 	body = (struct ieee802_1x_mka_sak_use_body *) mka_msg;
   1278 	ieee802_1x_mka_dump_sak_use_body(body);
   1279 
   1280 	if ((body_len != 0) && (body_len < 40)) {
   1281 		wpa_printf(MSG_ERROR,
   1282 			   "KaY: MKA Use SAK Packet Body Length (%zu bytes) should be 0, 40, or more octets",
   1283 			   body_len);
   1284 		return -1;
   1285 	}
   1286 
   1287 	/* TODO: what action should I take when peer does not support MACsec */
   1288 	if (body_len == 0) {
   1289 		wpa_printf(MSG_WARNING, "KaY: Peer does not support MACsec");
   1290 		return 0;
   1291 	}
   1292 
   1293 	/* TODO: when the plain tx or rx of peer is true, should I change
   1294 	 * the attribute of controlled port
   1295 	 */
   1296 	if (body->prx)
   1297 		wpa_printf(MSG_WARNING, "KaY: peer's plain rx are TRUE");
   1298 
   1299 	if (body->ptx)
   1300 		wpa_printf(MSG_WARNING, "KaY: peer's plain tx are TRUE");
   1301 
   1302 	/* check latest key is valid */
   1303 	if (body->ltx || body->lrx) {
   1304 		found = FALSE;
   1305 		os_memcpy(ki.mi, body->lsrv_mi, sizeof(ki.mi));
   1306 		ki.kn = be_to_host32(body->lkn);
   1307 		dl_list_for_each(sa_key, &participant->sak_list,
   1308 				 struct data_key, list) {
   1309 			if (is_ki_equal(&sa_key->key_identifier, &ki)) {
   1310 				found = TRUE;
   1311 				break;
   1312 			}
   1313 		}
   1314 		if (!found) {
   1315 			wpa_printf(MSG_WARNING, "KaY: Latest key is invalid");
   1316 			return -1;
   1317 		}
   1318 		if (os_memcmp(participant->lki.mi, body->lsrv_mi,
   1319 			      sizeof(participant->lki.mi)) == 0 &&
   1320 		    be_to_host32(body->lkn) == participant->lki.kn &&
   1321 		    body->lan == participant->lan) {
   1322 			peer->sak_used = TRUE;
   1323 		}
   1324 		if (body->ltx && peer->is_key_server) {
   1325 			ieee802_1x_cp_set_servertransmitting(kay->cp, TRUE);
   1326 			ieee802_1x_cp_sm_step(kay->cp);
   1327 		}
   1328 	}
   1329 
   1330 	/* check old key is valid */
   1331 	if (body->otx || body->orx) {
   1332 		if (os_memcmp(participant->oki.mi, body->osrv_mi,
   1333 			      sizeof(participant->oki.mi)) != 0 ||
   1334 		    be_to_host32(body->okn) != participant->oki.kn ||
   1335 		    body->oan != participant->oan) {
   1336 			wpa_printf(MSG_WARNING, "KaY: Old key is invalid");
   1337 			return -1;
   1338 		}
   1339 	}
   1340 
   1341 	/* TODO: how to set the MACsec hardware when delay_protect is true */
   1342 	if (body->delay_protect &&
   1343 	    (!be_to_host32(body->llpn) || !be_to_host32(body->olpn))) {
   1344 		wpa_printf(MSG_WARNING,
   1345 			   "KaY: Lowest packet number should greater than 0 when delay_protect is TRUE");
   1346 		return -1;
   1347 	}
   1348 
   1349 	/* check all live peer have used the sak for receiving sa */
   1350 	all_receiving = TRUE;
   1351 	dl_list_for_each(peer, &participant->live_peers,
   1352 			 struct ieee802_1x_kay_peer, list) {
   1353 		if (!peer->sak_used) {
   1354 			all_receiving = FALSE;
   1355 			break;
   1356 		}
   1357 	}
   1358 	if (all_receiving) {
   1359 		participant->to_dist_sak = FALSE;
   1360 		ieee802_1x_cp_set_allreceiving(kay->cp, TRUE);
   1361 		ieee802_1x_cp_sm_step(kay->cp);
   1362 	}
   1363 
   1364 	/* if i'm key server, and detects peer member pn exhaustion, rekey.*/
   1365 	lpn = be_to_host32(body->llpn);
   1366 	if (lpn > kay->pn_exhaustion) {
   1367 		if (participant->is_key_server) {
   1368 			participant->new_sak = TRUE;
   1369 			wpa_printf(MSG_WARNING, "KaY: Peer LPN exhaustion");
   1370 		}
   1371 	}
   1372 
   1373 	found = FALSE;
   1374 	dl_list_for_each(txsa, &participant->txsc->sa_list,
   1375 			 struct transmit_sa, list) {
   1376 		if (sa_key != NULL && txsa->pkey == sa_key) {
   1377 			found = TRUE;
   1378 			break;
   1379 		}
   1380 	}
   1381 	if (!found) {
   1382 		wpa_printf(MSG_WARNING, "KaY: Can't find txsa");
   1383 		return -1;
   1384 	}
   1385 
   1386 	/* FIXME: Secy creates txsa with default npn. If MKA detected Latest Key
   1387 	 * npn is larger than txsa's npn, set it to txsa.
   1388 	 */
   1389 	secy_get_transmit_next_pn(kay, txsa);
   1390 	if (lpn > txsa->next_pn) {
   1391 		secy_set_transmit_next_pn(kay, txsa);
   1392 		wpa_printf(MSG_INFO, "KaY: update lpn =0x%x", lpn);
   1393 	}
   1394 
   1395 	return 0;
   1396 }
   1397 
   1398 
   1399 /**
   1400  * ieee802_1x_mka_dist_sak_body_present
   1401  */
   1402 static Boolean
   1403 ieee802_1x_mka_dist_sak_body_present(
   1404 	struct ieee802_1x_mka_participant *participant)
   1405 {
   1406 	return participant->to_dist_sak && participant->new_key;
   1407 }
   1408 
   1409 
   1410 /**
   1411  * ieee802_1x_kay_get_dist_sak_length
   1412  */
   1413 static int
   1414 ieee802_1x_mka_get_dist_sak_length(
   1415 	struct ieee802_1x_mka_participant *participant)
   1416 {
   1417 	int length = MKA_HDR_LEN;
   1418 	unsigned int cs_index = participant->kay->macsec_csindex;
   1419 
   1420 	if (participant->advised_desired && cs_index < CS_TABLE_SIZE) {
   1421 		length = sizeof(struct ieee802_1x_mka_dist_sak_body);
   1422 		if (cs_index != DEFAULT_CS_INDEX)
   1423 			length += CS_ID_LEN;
   1424 
   1425 		length += cipher_suite_tbl[cs_index].sak_len + 8;
   1426 	}
   1427 
   1428 	return MKA_ALIGN_LENGTH(length);
   1429 }
   1430 
   1431 
   1432 /**
   1433  * ieee802_1x_mka_encode_dist_sak_body -
   1434  */
   1435 static int
   1436 ieee802_1x_mka_encode_dist_sak_body(
   1437 	struct ieee802_1x_mka_participant *participant,
   1438 	struct wpabuf *buf)
   1439 {
   1440 	struct ieee802_1x_mka_dist_sak_body *body;
   1441 	struct data_key *sak;
   1442 	unsigned int length;
   1443 	unsigned int cs_index;
   1444 	int sak_pos;
   1445 
   1446 	length = ieee802_1x_mka_get_dist_sak_length(participant);
   1447 	body = wpabuf_put(buf, length);
   1448 	body->type = MKA_DISTRIBUTED_SAK;
   1449 	set_mka_param_body_len(body, length - MKA_HDR_LEN);
   1450 	if (length == MKA_HDR_LEN) {
   1451 		body->confid_offset = 0;
   1452 		body->dan = 0;
   1453 		return 0;
   1454 	}
   1455 
   1456 	sak = participant->new_key;
   1457 	body->confid_offset = sak->confidentiality_offset;
   1458 	body->dan = sak->an;
   1459 	body->kn = host_to_be32(sak->key_identifier.kn);
   1460 	cs_index = participant->kay->macsec_csindex;
   1461 	sak_pos = 0;
   1462 	if (cs_index >= CS_TABLE_SIZE)
   1463 		return -1;
   1464 	if (cs_index != DEFAULT_CS_INDEX) {
   1465 		be64 cs;
   1466 
   1467 		cs = host_to_be64(cipher_suite_tbl[cs_index].id);
   1468 		os_memcpy(body->sak, &cs, CS_ID_LEN);
   1469 		sak_pos = CS_ID_LEN;
   1470 	}
   1471 	if (aes_wrap(participant->kek.key, 16,
   1472 		     cipher_suite_tbl[cs_index].sak_len / 8,
   1473 		     sak->key, body->sak + sak_pos)) {
   1474 		wpa_printf(MSG_ERROR, "KaY: AES wrap failed");
   1475 		return -1;
   1476 	}
   1477 
   1478 	ieee802_1x_mka_dump_dist_sak_body(body);
   1479 
   1480 	return 0;
   1481 }
   1482 
   1483 
   1484 /**
   1485  * ieee802_1x_kay_init_data_key -
   1486  */
   1487 static void ieee802_1x_kay_init_data_key(struct data_key *pkey)
   1488 {
   1489 	pkey->transmits = TRUE;
   1490 	pkey->receives = TRUE;
   1491 	os_get_time(&pkey->created_time);
   1492 
   1493 	pkey->user = 1;
   1494 }
   1495 
   1496 
   1497 /**
   1498  * ieee802_1x_kay_decode_dist_sak_body -
   1499  */
   1500 static int
   1501 ieee802_1x_mka_decode_dist_sak_body(
   1502 	struct ieee802_1x_mka_participant *participant,
   1503 	const u8 *mka_msg, size_t msg_len)
   1504 {
   1505 	struct ieee802_1x_mka_hdr *hdr;
   1506 	struct ieee802_1x_mka_dist_sak_body *body;
   1507 	struct ieee802_1x_kay_peer *peer;
   1508 	struct macsec_ciphersuite *cs;
   1509 	size_t body_len;
   1510 	struct data_key *sa_key = NULL;
   1511 	int sak_len;
   1512 	u8 *wrap_sak;
   1513 	u8 *unwrap_sak;
   1514 	struct ieee802_1x_kay *kay = participant->kay;
   1515 
   1516 	hdr = (struct ieee802_1x_mka_hdr *) mka_msg;
   1517 	body_len = get_mka_param_body_len(hdr);
   1518 	if ((body_len != 0) && (body_len != 28) && (body_len < 36)) {
   1519 		wpa_printf(MSG_ERROR,
   1520 			   "KaY: MKA Use SAK Packet Body Length (%zu bytes) should be 0, 28, 36, or more octets",
   1521 			   body_len);
   1522 		return -1;
   1523 	}
   1524 
   1525 	if (!participant->principal) {
   1526 		wpa_printf(MSG_ERROR,
   1527 			   "KaY: I can't accept the distributed SAK as I am not principal");
   1528 		return -1;
   1529 	}
   1530 	if (participant->is_key_server) {
   1531 		wpa_printf(MSG_ERROR,
   1532 			   "KaY: I can't accept the distributed SAK as myself is key server ");
   1533 		return -1;
   1534 	}
   1535 	if (!kay->macsec_desired ||
   1536 	    kay->macsec_capable == MACSEC_CAP_NOT_IMPLEMENTED) {
   1537 		wpa_printf(MSG_ERROR,
   1538 			   "KaY: I am not MACsec-desired or without MACsec capable");
   1539 		return -1;
   1540 	}
   1541 
   1542 	peer = ieee802_1x_kay_get_live_peer(participant,
   1543 					    participant->current_peer_id.mi);
   1544 	if (!peer) {
   1545 		wpa_printf(MSG_ERROR,
   1546 			   "KaY: The key server is not in my live peers list");
   1547 		return -1;
   1548 	}
   1549 	if (!sci_equal(&kay->key_server_sci, &peer->sci)) {
   1550 		wpa_printf(MSG_ERROR, "KaY: The key server is not elected");
   1551 		return -1;
   1552 	}
   1553 
   1554 	if (body_len == 0) {
   1555 		kay->authenticated = TRUE;
   1556 		kay->secured = FALSE;
   1557 		kay->failed = FALSE;
   1558 		participant->advised_desired = FALSE;
   1559 		ieee802_1x_cp_connect_authenticated(kay->cp);
   1560 		ieee802_1x_cp_sm_step(kay->cp);
   1561 		wpa_printf(MSG_WARNING, "KaY:The Key server advise no MACsec");
   1562 		participant->to_use_sak = FALSE;
   1563 		return 0;
   1564 	}
   1565 
   1566 	participant->advised_desired = TRUE;
   1567 	kay->authenticated = FALSE;
   1568 	kay->secured = TRUE;
   1569 	kay->failed = FALSE;
   1570 	ieee802_1x_cp_connect_secure(kay->cp);
   1571 	ieee802_1x_cp_sm_step(kay->cp);
   1572 
   1573 	body = (struct ieee802_1x_mka_dist_sak_body *)mka_msg;
   1574 	ieee802_1x_mka_dump_dist_sak_body(body);
   1575 	dl_list_for_each(sa_key, &participant->sak_list, struct data_key, list)
   1576 	{
   1577 		if (os_memcmp(sa_key->key_identifier.mi,
   1578 			      participant->current_peer_id.mi, MI_LEN) == 0 &&
   1579 		    sa_key->key_identifier.kn == be_to_host32(body->kn)) {
   1580 			wpa_printf(MSG_WARNING, "KaY:The Key has installed");
   1581 			return 0;
   1582 		}
   1583 	}
   1584 
   1585 	if (body_len == 28) {
   1586 		sak_len = DEFAULT_SA_KEY_LEN;
   1587 		wrap_sak =  body->sak;
   1588 		kay->macsec_csindex = DEFAULT_CS_INDEX;
   1589 		cs = &cipher_suite_tbl[kay->macsec_csindex];
   1590 	} else {
   1591 		cs = ieee802_1x_kay_get_cipher_suite(participant, body->sak);
   1592 		if (!cs) {
   1593 			wpa_printf(MSG_ERROR,
   1594 				   "KaY: I can't support the Cipher Suite advised by key server");
   1595 			return -1;
   1596 		}
   1597 		sak_len = cs->sak_len;
   1598 		wrap_sak = body->sak + CS_ID_LEN;
   1599 		kay->macsec_csindex = cs->index;
   1600 	}
   1601 
   1602 	unwrap_sak = os_zalloc(sak_len);
   1603 	if (!unwrap_sak) {
   1604 		wpa_printf(MSG_ERROR, "KaY-%s: Out of memory", __func__);
   1605 		return -1;
   1606 	}
   1607 	if (aes_unwrap(participant->kek.key, 16, sak_len >> 3, wrap_sak,
   1608 		       unwrap_sak)) {
   1609 		wpa_printf(MSG_ERROR, "KaY: AES unwrap failed");
   1610 		os_free(unwrap_sak);
   1611 		return -1;
   1612 	}
   1613 	wpa_hexdump(MSG_DEBUG, "\tAES Key Unwrap of SAK:", unwrap_sak, sak_len);
   1614 
   1615 	sa_key = os_zalloc(sizeof(*sa_key));
   1616 	if (!sa_key) {
   1617 		os_free(unwrap_sak);
   1618 		return -1;
   1619 	}
   1620 
   1621 	os_memcpy(&sa_key->key_identifier.mi, &participant->current_peer_id.mi,
   1622 		  MI_LEN);
   1623 	sa_key->key_identifier.kn = be_to_host32(body->kn);
   1624 
   1625 	sa_key->key = unwrap_sak;
   1626 	sa_key->key_len = sak_len;
   1627 
   1628 	sa_key->confidentiality_offset = body->confid_offset;
   1629 	sa_key->an = body->dan;
   1630 	ieee802_1x_kay_init_data_key(sa_key);
   1631 
   1632 	ieee802_1x_kay_use_data_key(sa_key);
   1633 	dl_list_add(&participant->sak_list, &sa_key->list);
   1634 
   1635 	ieee802_1x_cp_set_ciphersuite(kay->cp, cs->id);
   1636 	ieee802_1x_cp_sm_step(kay->cp);
   1637 	ieee802_1x_cp_set_offset(kay->cp, body->confid_offset);
   1638 	ieee802_1x_cp_sm_step(kay->cp);
   1639 	ieee802_1x_cp_set_distributedki(kay->cp, &sa_key->key_identifier);
   1640 	ieee802_1x_cp_set_distributedan(kay->cp, body->dan);
   1641 	ieee802_1x_cp_signal_newsak(kay->cp);
   1642 	ieee802_1x_cp_sm_step(kay->cp);
   1643 
   1644 	kay->rcvd_keys++;
   1645 	participant->to_use_sak = TRUE;
   1646 
   1647 	return 0;
   1648 }
   1649 
   1650 
   1651 /**
   1652  * ieee802_1x_mka_icv_body_present
   1653  */
   1654 static Boolean
   1655 ieee802_1x_mka_icv_body_present(struct ieee802_1x_mka_participant *participant)
   1656 {
   1657 	return TRUE;
   1658 }
   1659 
   1660 
   1661 /**
   1662  * ieee802_1x_kay_get_icv_length
   1663  */
   1664 static int
   1665 ieee802_1x_mka_get_icv_length(struct ieee802_1x_mka_participant *participant)
   1666 {
   1667 	int length;
   1668 
   1669 	length = sizeof(struct ieee802_1x_mka_icv_body);
   1670 	length += mka_alg_tbl[participant->kay->mka_algindex].icv_len;
   1671 
   1672 	return MKA_ALIGN_LENGTH(length);
   1673 }
   1674 
   1675 
   1676 /**
   1677  * ieee802_1x_mka_encode_icv_body -
   1678  */
   1679 static int
   1680 ieee802_1x_mka_encode_icv_body(struct ieee802_1x_mka_participant *participant,
   1681 			       struct wpabuf *buf)
   1682 {
   1683 	struct ieee802_1x_mka_icv_body *body;
   1684 	unsigned int length;
   1685 	u8 cmac[MAX_ICV_LEN];
   1686 
   1687 	length = ieee802_1x_mka_get_icv_length(participant);
   1688 	if (length != DEFAULT_ICV_LEN)  {
   1689 		body = wpabuf_put(buf, MKA_HDR_LEN);
   1690 		body->type = MKA_ICV_INDICATOR;
   1691 		set_mka_param_body_len(body, length - MKA_HDR_LEN);
   1692 	}
   1693 
   1694 	if (mka_alg_tbl[participant->kay->mka_algindex].icv_hash(
   1695 		    participant->ick.key, wpabuf_head(buf), buf->used, cmac)) {
   1696 		wpa_printf(MSG_ERROR, "KaY, omac1_aes_128 failed");
   1697 		return -1;
   1698 	}
   1699 
   1700 	if (length != DEFAULT_ICV_LEN)
   1701 		length -= MKA_HDR_LEN;
   1702 	os_memcpy(wpabuf_put(buf, length), cmac, length);
   1703 
   1704 	return 0;
   1705 }
   1706 
   1707 /**
   1708  * ieee802_1x_mka_decode_icv_body -
   1709  */
   1710 static u8 *
   1711 ieee802_1x_mka_decode_icv_body(struct ieee802_1x_mka_participant *participant,
   1712 			       const u8 *mka_msg, size_t msg_len)
   1713 {
   1714 	struct ieee802_1x_mka_hdr *hdr;
   1715 	struct ieee802_1x_mka_icv_body *body;
   1716 	size_t body_len;
   1717 	size_t left_len;
   1718 	u8 body_type;
   1719 	const u8 *pos;
   1720 
   1721 	pos = mka_msg;
   1722 	left_len = msg_len;
   1723 	while (left_len > (MKA_HDR_LEN + DEFAULT_ICV_LEN)) {
   1724 		hdr = (struct ieee802_1x_mka_hdr *) pos;
   1725 		body_len = get_mka_param_body_len(hdr);
   1726 		body_type = get_mka_param_body_type(hdr);
   1727 
   1728 		if (left_len < (body_len + MKA_HDR_LEN))
   1729 			break;
   1730 
   1731 		if (body_type != MKA_ICV_INDICATOR) {
   1732 			left_len -= MKA_HDR_LEN + body_len;
   1733 			pos += MKA_HDR_LEN + body_len;
   1734 			continue;
   1735 		}
   1736 
   1737 		body = (struct ieee802_1x_mka_icv_body *)pos;
   1738 		if (body_len
   1739 			< mka_alg_tbl[participant->kay->mka_algindex].icv_len) {
   1740 			return NULL;
   1741 		}
   1742 
   1743 		return body->icv;
   1744 	}
   1745 
   1746 	return (u8 *) (mka_msg + msg_len - DEFAULT_ICV_LEN);
   1747 }
   1748 
   1749 
   1750 /**
   1751  * ieee802_1x_mka_decode_dist_cak_body-
   1752  */
   1753 static int
   1754 ieee802_1x_mka_decode_dist_cak_body(
   1755 	struct ieee802_1x_mka_participant *participant,
   1756 	const u8 *mka_msg, size_t msg_len)
   1757 {
   1758 	struct ieee802_1x_mka_hdr *hdr;
   1759 	size_t body_len;
   1760 
   1761 	hdr = (struct ieee802_1x_mka_hdr *) mka_msg;
   1762 	body_len = get_mka_param_body_len(hdr);
   1763 	if (body_len < 28) {
   1764 		wpa_printf(MSG_ERROR,
   1765 			   "KaY: MKA Use SAK Packet Body Length (%zu bytes) should be 28 or more octets",
   1766 			   body_len);
   1767 		return -1;
   1768 	}
   1769 
   1770 	return 0;
   1771 }
   1772 
   1773 
   1774 /**
   1775  * ieee802_1x_mka_decode_kmd_body -
   1776  */
   1777 static int
   1778 ieee802_1x_mka_decode_kmd_body(
   1779 	struct ieee802_1x_mka_participant *participant,
   1780 	const u8 *mka_msg, size_t msg_len)
   1781 {
   1782 	struct ieee802_1x_mka_hdr *hdr;
   1783 	size_t body_len;
   1784 
   1785 	hdr = (struct ieee802_1x_mka_hdr *) mka_msg;
   1786 	body_len = get_mka_param_body_len(hdr);
   1787 	if (body_len < 5) {
   1788 		wpa_printf(MSG_ERROR,
   1789 			   "KaY: MKA Use SAK Packet Body Length (%zu bytes) should be 5 or more octets",
   1790 			   body_len);
   1791 		return -1;
   1792 	}
   1793 
   1794 	return 0;
   1795 }
   1796 
   1797 
   1798 /**
   1799  * ieee802_1x_mka_decode_announce_body -
   1800  */
   1801 static int ieee802_1x_mka_decode_announce_body(
   1802 	struct ieee802_1x_mka_participant *participant,
   1803 	const u8 *mka_msg, size_t msg_len)
   1804 {
   1805 	return 0;
   1806 }
   1807 
   1808 
   1809 struct mka_param_body_handler {
   1810 	int (*body_tx)(struct ieee802_1x_mka_participant *participant,
   1811 		       struct wpabuf *buf);
   1812 	int (*body_rx)(struct ieee802_1x_mka_participant *participant,
   1813 		       const u8 *mka_msg, size_t msg_len);
   1814 	int (*body_length)(struct ieee802_1x_mka_participant *participant);
   1815 	Boolean (*body_present)(struct ieee802_1x_mka_participant *participant);
   1816 };
   1817 
   1818 
   1819 static struct mka_param_body_handler mka_body_handler[] = {
   1820 	/* basic parameter set */
   1821 	{
   1822 		.body_tx      = ieee802_1x_mka_encode_basic_body,
   1823 		.body_rx      = NULL,
   1824 		.body_length  = ieee802_1x_mka_basic_body_length,
   1825 		.body_present = ieee802_1x_mka_basic_body_present
   1826 	},
   1827 
   1828 	/* live peer list parameter set */
   1829 	{
   1830 		.body_tx      = ieee802_1x_mka_encode_live_peer_body,
   1831 		.body_rx      = ieee802_1x_mka_decode_live_peer_body,
   1832 		.body_length  = ieee802_1x_mka_get_live_peer_length,
   1833 		.body_present = ieee802_1x_mka_live_peer_body_present
   1834 	},
   1835 
   1836 	/* potential peer list parameter set */
   1837 	{
   1838 		.body_tx      = ieee802_1x_mka_encode_potential_peer_body,
   1839 		.body_rx      = ieee802_1x_mka_decode_potential_peer_body,
   1840 		.body_length  = ieee802_1x_mka_get_potential_peer_length,
   1841 		.body_present = ieee802_1x_mka_potential_peer_body_present
   1842 	},
   1843 
   1844 	/* sak use parameter set */
   1845 	{
   1846 		.body_tx      = ieee802_1x_mka_encode_sak_use_body,
   1847 		.body_rx      = ieee802_1x_mka_decode_sak_use_body,
   1848 		.body_length  = ieee802_1x_mka_get_sak_use_length,
   1849 		.body_present = ieee802_1x_mka_sak_use_body_present
   1850 	},
   1851 
   1852 	/* distribute sak parameter set */
   1853 	{
   1854 		.body_tx      = ieee802_1x_mka_encode_dist_sak_body,
   1855 		.body_rx      = ieee802_1x_mka_decode_dist_sak_body,
   1856 		.body_length  = ieee802_1x_mka_get_dist_sak_length,
   1857 		.body_present = ieee802_1x_mka_dist_sak_body_present
   1858 	},
   1859 
   1860 	/* distribute cak parameter set */
   1861 	{
   1862 		.body_tx      = NULL,
   1863 		.body_rx      = ieee802_1x_mka_decode_dist_cak_body,
   1864 		.body_length  = NULL,
   1865 		.body_present = NULL
   1866 	},
   1867 
   1868 	/* kmd parameter set */
   1869 	{
   1870 		.body_tx      = NULL,
   1871 		.body_rx      = ieee802_1x_mka_decode_kmd_body,
   1872 		.body_length  = NULL,
   1873 		.body_present = NULL
   1874 	},
   1875 
   1876 	/* announce parameter set */
   1877 	{
   1878 		.body_tx      = NULL,
   1879 		.body_rx      = ieee802_1x_mka_decode_announce_body,
   1880 		.body_length  = NULL,
   1881 		.body_present = NULL
   1882 	},
   1883 
   1884 	/* icv parameter set */
   1885 	{
   1886 		.body_tx      = ieee802_1x_mka_encode_icv_body,
   1887 		.body_rx      = NULL,
   1888 		.body_length  = ieee802_1x_mka_get_icv_length,
   1889 		.body_present = ieee802_1x_mka_icv_body_present
   1890 	},
   1891 };
   1892 
   1893 
   1894 /**
   1895  * ieee802_1x_kay_use_data_key - Take reference on a key
   1896  */
   1897 static void ieee802_1x_kay_use_data_key(struct data_key *pkey)
   1898 {
   1899 	pkey->user++;
   1900 }
   1901 
   1902 
   1903 /**
   1904  * ieee802_1x_kay_deinit_data_key - Release reference on a key and
   1905  * free if there are no remaining users
   1906  */
   1907 static void ieee802_1x_kay_deinit_data_key(struct data_key *pkey)
   1908 {
   1909 	if (!pkey)
   1910 		return;
   1911 
   1912 	pkey->user--;
   1913 	if (pkey->user > 1)
   1914 		return;
   1915 
   1916 	os_free(pkey->key);
   1917 	os_free(pkey);
   1918 }
   1919 
   1920 
   1921 /**
   1922  * ieee802_1x_kay_generate_new_sak -
   1923  */
   1924 static int
   1925 ieee802_1x_kay_generate_new_sak(struct ieee802_1x_mka_participant *participant)
   1926 {
   1927 	struct data_key *sa_key = NULL;
   1928 	struct ieee802_1x_kay_peer *peer;
   1929 	struct ieee802_1x_kay *kay = participant->kay;
   1930 	int ctx_len, ctx_offset;
   1931 	u8 *context;
   1932 	unsigned int key_len;
   1933 	u8 *key;
   1934 	struct macsec_ciphersuite *cs;
   1935 
   1936 	/* check condition for generating a fresh SAK:
   1937 	 * must have one live peer
   1938 	 * and MKA life time elapse since last distribution
   1939 	 * or potential peer is empty
   1940 	 */
   1941 	if (dl_list_empty(&participant->live_peers)) {
   1942 		wpa_printf(MSG_ERROR,
   1943 			   "KaY: Live peers list must not empty when generating fresh SAK");
   1944 		return -1;
   1945 	}
   1946 
   1947 	/* FIXME: A fresh SAK not generated until
   1948 	 * the live peer list contains at least one peer and
   1949 	 * MKA life time has elapsed since the prior SAK was first distributed,
   1950 	 * or the Key server's potential peer is empty
   1951 	 * but I can't understand the second item, so
   1952 	 * here only check first item and ingore
   1953 	 *   && (!dl_list_empty(&participant->potential_peers))) {
   1954 	 */
   1955 	if ((time(NULL) - kay->dist_time) < MKA_LIFE_TIME / 1000) {
   1956 		wpa_printf(MSG_ERROR,
   1957 			   "KaY: Life time have not elapsed since prior SAK distributed");
   1958 		return -1;
   1959 	}
   1960 
   1961 	cs = &cipher_suite_tbl[kay->macsec_csindex];
   1962 	key_len = cs->sak_len;
   1963 	key = os_zalloc(key_len);
   1964 	if (!key) {
   1965 		wpa_printf(MSG_ERROR, "KaY-%s: Out of memory", __func__);
   1966 		return -1;
   1967 	}
   1968 
   1969 	ctx_len = key_len + sizeof(kay->dist_kn);
   1970 	dl_list_for_each(peer, &participant->live_peers,
   1971 			 struct ieee802_1x_kay_peer, list)
   1972 		ctx_len += sizeof(peer->mi);
   1973 	ctx_len += sizeof(participant->mi);
   1974 
   1975 	context = os_zalloc(ctx_len);
   1976 	if (!context)
   1977 		goto fail;
   1978 
   1979 	ctx_offset = 0;
   1980 	if (os_get_random(context + ctx_offset, key_len) < 0)
   1981 		goto fail;
   1982 
   1983 	ctx_offset += key_len;
   1984 	dl_list_for_each(peer, &participant->live_peers,
   1985 			 struct ieee802_1x_kay_peer, list) {
   1986 		os_memcpy(context + ctx_offset, peer->mi, sizeof(peer->mi));
   1987 		ctx_offset += sizeof(peer->mi);
   1988 	}
   1989 	os_memcpy(context + ctx_offset, participant->mi,
   1990 		  sizeof(participant->mi));
   1991 	ctx_offset += sizeof(participant->mi);
   1992 	os_memcpy(context + ctx_offset, &kay->dist_kn, sizeof(kay->dist_kn));
   1993 
   1994 	if (key_len == 16) {
   1995 		ieee802_1x_sak_128bits_aes_cmac(participant->cak.key,
   1996 						context, ctx_len, key);
   1997 	} else if (key_len == 32) {
   1998 		ieee802_1x_sak_128bits_aes_cmac(participant->cak.key,
   1999 						context, ctx_len, key);
   2000 	} else {
   2001 		wpa_printf(MSG_ERROR, "KaY: SAK Length not support");
   2002 		goto fail;
   2003 	}
   2004 	wpa_hexdump(MSG_DEBUG, "KaY: generated new SAK", key, key_len);
   2005 	os_free(context);
   2006 	context = NULL;
   2007 
   2008 	sa_key = os_zalloc(sizeof(*sa_key));
   2009 	if (!sa_key) {
   2010 		wpa_printf(MSG_ERROR, "KaY-%s: Out of memory", __func__);
   2011 		goto fail;
   2012 	}
   2013 
   2014 	sa_key->key = key;
   2015 	sa_key->key_len = key_len;
   2016 	os_memcpy(sa_key->key_identifier.mi, participant->mi, MI_LEN);
   2017 	sa_key->key_identifier.kn = kay->dist_kn;
   2018 
   2019 	sa_key->confidentiality_offset = kay->macsec_confidentiality;
   2020 	sa_key->an = kay->dist_an;
   2021 	ieee802_1x_kay_init_data_key(sa_key);
   2022 
   2023 	participant->new_key = sa_key;
   2024 
   2025 	ieee802_1x_kay_use_data_key(sa_key);
   2026 	dl_list_add(&participant->sak_list, &sa_key->list);
   2027 
   2028 	ieee802_1x_cp_set_ciphersuite(kay->cp, cs->id);
   2029 	ieee802_1x_cp_sm_step(kay->cp);
   2030 	ieee802_1x_cp_set_offset(kay->cp, kay->macsec_confidentiality);
   2031 	ieee802_1x_cp_sm_step(kay->cp);
   2032 	ieee802_1x_cp_set_distributedki(kay->cp, &sa_key->key_identifier);
   2033 	ieee802_1x_cp_set_distributedan(kay->cp, sa_key->an);
   2034 	ieee802_1x_cp_signal_newsak(kay->cp);
   2035 	ieee802_1x_cp_sm_step(kay->cp);
   2036 
   2037 	dl_list_for_each(peer, &participant->live_peers,
   2038 			 struct ieee802_1x_kay_peer, list)
   2039 		peer->sak_used = FALSE;
   2040 
   2041 	kay->dist_kn++;
   2042 	kay->dist_an++;
   2043 	if (kay->dist_an > 3)
   2044 		kay->dist_an = 0;
   2045 
   2046 	kay->dist_time = time(NULL);
   2047 
   2048 	return 0;
   2049 
   2050 fail:
   2051 	os_free(key);
   2052 	os_free(context);
   2053 	return -1;
   2054 }
   2055 
   2056 
   2057 static int compare_priorities(const struct ieee802_1x_kay_peer *peer,
   2058 			      const struct ieee802_1x_kay_peer *other)
   2059 {
   2060 	if (peer->key_server_priority < other->key_server_priority)
   2061 		return -1;
   2062 	if (other->key_server_priority < peer->key_server_priority)
   2063 		return 1;
   2064 
   2065 	return os_memcmp(peer->sci.addr, other->sci.addr, ETH_ALEN);
   2066 }
   2067 
   2068 
   2069 /**
   2070  * ieee802_1x_kay_elect_key_server - elect the key server
   2071  * when to elect: whenever the live peers list changes
   2072  */
   2073 static int
   2074 ieee802_1x_kay_elect_key_server(struct ieee802_1x_mka_participant *participant)
   2075 {
   2076 	struct ieee802_1x_kay_peer *peer;
   2077 	struct ieee802_1x_kay_peer *key_server = NULL;
   2078 	struct ieee802_1x_kay *kay = participant->kay;
   2079 	Boolean i_is_key_server;
   2080 
   2081 	if (participant->is_obliged_key_server) {
   2082 		participant->new_sak = TRUE;
   2083 		participant->to_dist_sak = FALSE;
   2084 		ieee802_1x_cp_set_electedself(kay->cp, TRUE);
   2085 		return 0;
   2086 	}
   2087 
   2088 	/* elect the key server among the peers */
   2089 	dl_list_for_each(peer, &participant->live_peers,
   2090 			 struct ieee802_1x_kay_peer, list) {
   2091 		if (!peer->is_key_server)
   2092 			continue;
   2093 
   2094 		if (!key_server) {
   2095 			key_server = peer;
   2096 			continue;
   2097 		}
   2098 
   2099 		if (compare_priorities(peer, key_server) < 0)
   2100 			key_server = peer;
   2101 	}
   2102 
   2103 	/* elect the key server between me and the above elected peer */
   2104 	i_is_key_server = FALSE;
   2105 	if (key_server && participant->can_be_key_server) {
   2106 		struct ieee802_1x_kay_peer tmp;
   2107 
   2108 		tmp.key_server_priority = kay->actor_priority;
   2109 		os_memcpy(&tmp.sci, &kay->actor_sci, sizeof(tmp.sci));
   2110 		if (compare_priorities(&tmp, key_server) < 0)
   2111 			i_is_key_server = TRUE;
   2112 	} else if (participant->can_be_key_server) {
   2113 		i_is_key_server = TRUE;
   2114 	}
   2115 
   2116 	if (i_is_key_server) {
   2117 		ieee802_1x_cp_set_electedself(kay->cp, TRUE);
   2118 		if (!sci_equal(&kay->key_server_sci, &kay->actor_sci)) {
   2119 			ieee802_1x_cp_signal_chgdserver(kay->cp);
   2120 			ieee802_1x_cp_sm_step(kay->cp);
   2121 		}
   2122 
   2123 		participant->is_key_server = TRUE;
   2124 		participant->principal = TRUE;
   2125 		participant->new_sak = TRUE;
   2126 		wpa_printf(MSG_DEBUG, "KaY: I is elected as key server");
   2127 		participant->to_dist_sak = FALSE;
   2128 		participant->is_elected = TRUE;
   2129 
   2130 		os_memcpy(&kay->key_server_sci, &kay->actor_sci,
   2131 			  sizeof(kay->key_server_sci));
   2132 		kay->key_server_priority = kay->actor_priority;
   2133 	} else if (key_server) {
   2134 		ieee802_1x_cp_set_electedself(kay->cp, FALSE);
   2135 		if (!sci_equal(&kay->key_server_sci, &key_server->sci)) {
   2136 			ieee802_1x_cp_signal_chgdserver(kay->cp);
   2137 			ieee802_1x_cp_sm_step(kay->cp);
   2138 		}
   2139 
   2140 		participant->is_key_server = FALSE;
   2141 		participant->principal = TRUE;
   2142 		participant->is_elected = TRUE;
   2143 
   2144 		os_memcpy(&kay->key_server_sci, &key_server->sci,
   2145 			  sizeof(kay->key_server_sci));
   2146 		kay->key_server_priority = key_server->key_server_priority;
   2147 	} else {
   2148 		participant->principal = FALSE;
   2149 		participant->is_key_server = FALSE;
   2150 		participant->is_elected = FALSE;
   2151 	}
   2152 
   2153 	return 0;
   2154 }
   2155 
   2156 
   2157 /**
   2158  * ieee802_1x_kay_decide_macsec_use - the key server determinate
   2159  *		 how to use MACsec: whether use MACsec and its capability
   2160  * protectFrames will be advised if the key server and one of its live peers are
   2161  * MACsec capable and one of those request MACsec protection
   2162  */
   2163 static int
   2164 ieee802_1x_kay_decide_macsec_use(
   2165 	struct ieee802_1x_mka_participant *participant)
   2166 {
   2167 	struct ieee802_1x_kay *kay = participant->kay;
   2168 	struct ieee802_1x_kay_peer *peer;
   2169 	enum macsec_cap less_capability;
   2170 	Boolean has_peer;
   2171 
   2172 	if (!participant->is_key_server)
   2173 		return -1;
   2174 
   2175 	/* key server self is MACsec-desired and requesting MACsec */
   2176 	if (!kay->macsec_desired) {
   2177 		participant->advised_desired = FALSE;
   2178 		return -1;
   2179 	}
   2180 	if (kay->macsec_capable == MACSEC_CAP_NOT_IMPLEMENTED) {
   2181 		participant->advised_desired = FALSE;
   2182 		return -1;
   2183 	}
   2184 	less_capability = kay->macsec_capable;
   2185 
   2186 	/* at least one of peers is MACsec-desired and requesting MACsec */
   2187 	has_peer = FALSE;
   2188 	dl_list_for_each(peer, &participant->live_peers,
   2189 			 struct ieee802_1x_kay_peer, list) {
   2190 		if (!peer->macsec_desired)
   2191 			continue;
   2192 
   2193 		if (peer->macsec_capability == MACSEC_CAP_NOT_IMPLEMENTED)
   2194 			continue;
   2195 
   2196 		less_capability = (less_capability < peer->macsec_capability) ?
   2197 			less_capability : peer->macsec_capability;
   2198 		has_peer = TRUE;
   2199 	}
   2200 
   2201 	if (has_peer) {
   2202 		participant->advised_desired = TRUE;
   2203 		participant->advised_capability = less_capability;
   2204 		kay->authenticated = FALSE;
   2205 		kay->secured = TRUE;
   2206 		kay->failed = FALSE;
   2207 		ieee802_1x_cp_connect_secure(kay->cp);
   2208 		ieee802_1x_cp_sm_step(kay->cp);
   2209 	} else {
   2210 		participant->advised_desired = FALSE;
   2211 		participant->advised_capability = MACSEC_CAP_NOT_IMPLEMENTED;
   2212 		participant->to_use_sak = FALSE;
   2213 		kay->authenticated = TRUE;
   2214 		kay->secured = FALSE;
   2215 		kay->failed = FALSE;
   2216 		kay->ltx_kn = 0;
   2217 		kay->ltx_an = 0;
   2218 		kay->lrx_kn = 0;
   2219 		kay->lrx_an = 0;
   2220 		kay->otx_kn = 0;
   2221 		kay->otx_an = 0;
   2222 		kay->orx_kn = 0;
   2223 		kay->orx_an = 0;
   2224 		ieee802_1x_cp_connect_authenticated(kay->cp);
   2225 		ieee802_1x_cp_sm_step(kay->cp);
   2226 	}
   2227 
   2228 	return 0;
   2229 }
   2230 
   2231 static const u8 pae_group_addr[ETH_ALEN] = {
   2232 	0x01, 0x80, 0xc2, 0x00, 0x00, 0x03
   2233 };
   2234 
   2235 
   2236 /**
   2237  * ieee802_1x_kay_encode_mkpdu -
   2238  */
   2239 static int
   2240 ieee802_1x_kay_encode_mkpdu(struct ieee802_1x_mka_participant *participant,
   2241 			    struct wpabuf *pbuf)
   2242 {
   2243 	unsigned int i;
   2244 	struct ieee8023_hdr *ether_hdr;
   2245 	struct ieee802_1x_hdr *eapol_hdr;
   2246 
   2247 	ether_hdr = wpabuf_put(pbuf, sizeof(*ether_hdr));
   2248 	os_memcpy(ether_hdr->dest, pae_group_addr, sizeof(ether_hdr->dest));
   2249 	os_memcpy(ether_hdr->src, participant->kay->actor_sci.addr,
   2250 		  sizeof(ether_hdr->dest));
   2251 	ether_hdr->ethertype = host_to_be16(ETH_P_EAPOL);
   2252 
   2253 	eapol_hdr = wpabuf_put(pbuf, sizeof(*eapol_hdr));
   2254 	eapol_hdr->version = EAPOL_VERSION;
   2255 	eapol_hdr->type = IEEE802_1X_TYPE_EAPOL_MKA;
   2256 	eapol_hdr->length = host_to_be16(pbuf->size - pbuf->used);
   2257 
   2258 	for (i = 0; i < ARRAY_SIZE(mka_body_handler); i++) {
   2259 		if (mka_body_handler[i].body_present &&
   2260 		    mka_body_handler[i].body_present(participant)) {
   2261 			if (mka_body_handler[i].body_tx(participant, pbuf))
   2262 				return -1;
   2263 		}
   2264 	}
   2265 
   2266 	return 0;
   2267 }
   2268 
   2269 /**
   2270  * ieee802_1x_participant_send_mkpdu -
   2271  */
   2272 static int
   2273 ieee802_1x_participant_send_mkpdu(
   2274 	struct ieee802_1x_mka_participant *participant)
   2275 {
   2276 	struct wpabuf *buf;
   2277 	struct ieee802_1x_kay *kay = participant->kay;
   2278 	size_t length = 0;
   2279 	unsigned int i;
   2280 
   2281 	wpa_printf(MSG_DEBUG, "KaY: to enpacket and send the MKPDU");
   2282 	length += sizeof(struct ieee802_1x_hdr) + sizeof(struct ieee8023_hdr);
   2283 	for (i = 0; i < ARRAY_SIZE(mka_body_handler); i++) {
   2284 		if (mka_body_handler[i].body_present &&
   2285 		    mka_body_handler[i].body_present(participant))
   2286 			length += mka_body_handler[i].body_length(participant);
   2287 	}
   2288 
   2289 	buf = wpabuf_alloc(length);
   2290 	if (!buf) {
   2291 		wpa_printf(MSG_ERROR, "KaY: out of memory");
   2292 		return -1;
   2293 	}
   2294 
   2295 	if (ieee802_1x_kay_encode_mkpdu(participant, buf)) {
   2296 		wpa_printf(MSG_ERROR, "KaY: encode mkpdu fail!");
   2297 		return -1;
   2298 	}
   2299 
   2300 	l2_packet_send(kay->l2_mka, NULL, 0, wpabuf_head(buf), wpabuf_len(buf));
   2301 	wpabuf_free(buf);
   2302 
   2303 	kay->active = TRUE;
   2304 	participant->active = TRUE;
   2305 
   2306 	return 0;
   2307 }
   2308 
   2309 
   2310 static void ieee802_1x_kay_deinit_transmit_sa(struct transmit_sa *psa);
   2311 
   2312 static void ieee802_1x_delete_transmit_sa(struct ieee802_1x_kay *kay,
   2313 					  struct transmit_sa *sa)
   2314 {
   2315 	secy_disable_transmit_sa(kay, sa);
   2316 	secy_delete_transmit_sa(kay, sa);
   2317 	ieee802_1x_kay_deinit_transmit_sa(sa);
   2318 }
   2319 
   2320 
   2321 /**
   2322  * ieee802_1x_participant_timer -
   2323  */
   2324 static void ieee802_1x_participant_timer(void *eloop_ctx, void *timeout_ctx)
   2325 {
   2326 	struct ieee802_1x_mka_participant *participant;
   2327 	struct ieee802_1x_kay *kay;
   2328 	struct ieee802_1x_kay_peer *peer, *pre_peer;
   2329 	time_t now = time(NULL);
   2330 	Boolean lp_changed;
   2331 	struct receive_sc *rxsc, *pre_rxsc;
   2332 	struct transmit_sa *txsa, *pre_txsa;
   2333 
   2334 	participant = (struct ieee802_1x_mka_participant *)eloop_ctx;
   2335 	kay = participant->kay;
   2336 	if (participant->cak_life) {
   2337 		if (now > participant->cak_life)
   2338 			goto delete_mka;
   2339 	}
   2340 
   2341 	/* should delete MKA instance if there are not live peers
   2342 	 * when the MKA life elapsed since its creating */
   2343 	if (participant->mka_life) {
   2344 		if (dl_list_empty(&participant->live_peers)) {
   2345 			if (now > participant->mka_life)
   2346 				goto delete_mka;
   2347 		} else {
   2348 			participant->mka_life = 0;
   2349 		}
   2350 	}
   2351 
   2352 	lp_changed = FALSE;
   2353 	dl_list_for_each_safe(peer, pre_peer, &participant->live_peers,
   2354 			      struct ieee802_1x_kay_peer, list) {
   2355 		if (now > peer->expire) {
   2356 			wpa_printf(MSG_DEBUG, "KaY: Live peer removed");
   2357 			wpa_hexdump(MSG_DEBUG, "\tMI: ", peer->mi,
   2358 				    sizeof(peer->mi));
   2359 			wpa_printf(MSG_DEBUG, "\tMN: %d", peer->mn);
   2360 			dl_list_for_each_safe(rxsc, pre_rxsc,
   2361 					      &participant->rxsc_list,
   2362 					      struct receive_sc, list) {
   2363 				if (sci_equal(&rxsc->sci, &peer->sci)) {
   2364 					ieee802_1x_kay_deinit_receive_sc(
   2365 						participant, rxsc);
   2366 					secy_delete_receive_sc(kay, rxsc);
   2367 				}
   2368 			}
   2369 			dl_list_del(&peer->list);
   2370 			os_free(peer);
   2371 			lp_changed = TRUE;
   2372 		}
   2373 	}
   2374 
   2375 	if (lp_changed) {
   2376 		if (dl_list_empty(&participant->live_peers)) {
   2377 			participant->advised_desired = FALSE;
   2378 			participant->advised_capability =
   2379 				MACSEC_CAP_NOT_IMPLEMENTED;
   2380 			participant->to_use_sak = FALSE;
   2381 			participant->ltx = FALSE;
   2382 			participant->lrx = FALSE;
   2383 			participant->otx = FALSE;
   2384 			participant->orx = FALSE;
   2385 			participant->is_key_server = FALSE;
   2386 			participant->is_elected = FALSE;
   2387 			kay->authenticated = TRUE;
   2388 			kay->secured = FALSE;
   2389 			kay->failed = FALSE;
   2390 			kay->ltx_kn = 0;
   2391 			kay->ltx_an = 0;
   2392 			kay->lrx_kn = 0;
   2393 			kay->lrx_an = 0;
   2394 			kay->otx_kn = 0;
   2395 			kay->otx_an = 0;
   2396 			kay->orx_kn = 0;
   2397 			kay->orx_an = 0;
   2398 			dl_list_for_each_safe(txsa, pre_txsa,
   2399 					      &participant->txsc->sa_list,
   2400 					      struct transmit_sa, list) {
   2401 				ieee802_1x_delete_transmit_sa(kay, txsa);
   2402 			}
   2403 
   2404 			ieee802_1x_cp_connect_authenticated(kay->cp);
   2405 			ieee802_1x_cp_sm_step(kay->cp);
   2406 		} else {
   2407 			ieee802_1x_kay_elect_key_server(participant);
   2408 			ieee802_1x_kay_decide_macsec_use(participant);
   2409 		}
   2410 	}
   2411 
   2412 	dl_list_for_each_safe(peer, pre_peer, &participant->potential_peers,
   2413 			      struct ieee802_1x_kay_peer, list) {
   2414 		if (now > peer->expire) {
   2415 			wpa_printf(MSG_DEBUG, "KaY: Potential peer removed");
   2416 			wpa_hexdump(MSG_DEBUG, "\tMI: ", peer->mi,
   2417 				    sizeof(peer->mi));
   2418 			wpa_printf(MSG_DEBUG, "\tMN: %d", peer->mn);
   2419 			dl_list_del(&peer->list);
   2420 			os_free(peer);
   2421 		}
   2422 	}
   2423 
   2424 	if (participant->new_sak) {
   2425 		if (!ieee802_1x_kay_generate_new_sak(participant))
   2426 			participant->to_dist_sak = TRUE;
   2427 
   2428 		participant->new_sak = FALSE;
   2429 	}
   2430 
   2431 	if (participant->retry_count < MAX_RETRY_CNT ||
   2432 	    participant->mode == PSK) {
   2433 		ieee802_1x_participant_send_mkpdu(participant);
   2434 		participant->retry_count++;
   2435 	}
   2436 
   2437 	eloop_register_timeout(MKA_HELLO_TIME / 1000, 0,
   2438 			       ieee802_1x_participant_timer,
   2439 			       participant, NULL);
   2440 
   2441 	return;
   2442 
   2443 delete_mka:
   2444 	kay->authenticated = FALSE;
   2445 	kay->secured = FALSE;
   2446 	kay->failed = TRUE;
   2447 	ieee802_1x_kay_delete_mka(kay, &participant->ckn);
   2448 }
   2449 
   2450 
   2451 /**
   2452  * ieee802_1x_kay_init_transmit_sa -
   2453  */
   2454 static struct transmit_sa *
   2455 ieee802_1x_kay_init_transmit_sa(struct transmit_sc *psc, u8 an, u32 next_PN,
   2456 				struct data_key *key)
   2457 {
   2458 	struct transmit_sa *psa;
   2459 
   2460 	key->tx_latest = TRUE;
   2461 	key->rx_latest = TRUE;
   2462 
   2463 	psa = os_zalloc(sizeof(*psa));
   2464 	if (!psa) {
   2465 		wpa_printf(MSG_ERROR, "%s: out of memory", __func__);
   2466 		return NULL;
   2467 	}
   2468 
   2469 	if (key->confidentiality_offset >= CONFIDENTIALITY_OFFSET_0 &&
   2470 	    key->confidentiality_offset <= CONFIDENTIALITY_OFFSET_50)
   2471 		psa->confidentiality = TRUE;
   2472 	else
   2473 		psa->confidentiality = FALSE;
   2474 
   2475 	psa->an = an;
   2476 	ieee802_1x_kay_use_data_key(key);
   2477 	psa->pkey = key;
   2478 	psa->next_pn = next_PN;
   2479 	psa->sc = psc;
   2480 
   2481 	os_get_time(&psa->created_time);
   2482 	psa->in_use = FALSE;
   2483 
   2484 	dl_list_add(&psc->sa_list, &psa->list);
   2485 	wpa_printf(MSG_DEBUG,
   2486 		   "KaY: Create transmit SA(an: %hhu, next_PN: %u) of SC",
   2487 		   an, next_PN);
   2488 
   2489 	return psa;
   2490 }
   2491 
   2492 
   2493 /**
   2494  * ieee802_1x_kay_deinit_transmit_sa -
   2495  */
   2496 static void ieee802_1x_kay_deinit_transmit_sa(struct transmit_sa *psa)
   2497 {
   2498 	ieee802_1x_kay_deinit_data_key(psa->pkey);
   2499 	psa->pkey = NULL;
   2500 	wpa_printf(MSG_DEBUG,
   2501 		   "KaY: Delete transmit SA(an: %hhu) of SC",
   2502 		   psa->an);
   2503 	dl_list_del(&psa->list);
   2504 	os_free(psa);
   2505 }
   2506 
   2507 
   2508 /**
   2509  * init_transmit_sc -
   2510  */
   2511 static struct transmit_sc *
   2512 ieee802_1x_kay_init_transmit_sc(const struct ieee802_1x_mka_sci *sci)
   2513 {
   2514 	struct transmit_sc *psc;
   2515 
   2516 	psc = os_zalloc(sizeof(*psc));
   2517 	if (!psc) {
   2518 		wpa_printf(MSG_ERROR, "%s: out of memory", __func__);
   2519 		return NULL;
   2520 	}
   2521 	os_memcpy(&psc->sci, sci, sizeof(psc->sci));
   2522 
   2523 	os_get_time(&psc->created_time);
   2524 	psc->transmitting = FALSE;
   2525 	psc->encoding_sa = FALSE;
   2526 	psc->enciphering_sa = FALSE;
   2527 
   2528 	dl_list_init(&psc->sa_list);
   2529 	wpa_printf(MSG_DEBUG, "KaY: Create transmit SC");
   2530 	wpa_hexdump(MSG_DEBUG, "SCI: ", (u8 *)sci , sizeof(*sci));
   2531 
   2532 	return psc;
   2533 }
   2534 
   2535 
   2536 /**
   2537  * ieee802_1x_kay_deinit_transmit_sc -
   2538  */
   2539 static void
   2540 ieee802_1x_kay_deinit_transmit_sc(
   2541 	struct ieee802_1x_mka_participant *participant, struct transmit_sc *psc)
   2542 {
   2543 	struct transmit_sa *psa, *tmp;
   2544 
   2545 	wpa_printf(MSG_DEBUG, "KaY: Delete transmit SC");
   2546 	dl_list_for_each_safe(psa, tmp, &psc->sa_list, struct transmit_sa, list)
   2547 		ieee802_1x_delete_transmit_sa(participant->kay, psa);
   2548 
   2549 	os_free(psc);
   2550 }
   2551 
   2552 
   2553 /****************** Interface between CP and KAY *********************/
   2554 /**
   2555  * ieee802_1x_kay_set_latest_sa_attr -
   2556  */
   2557 int ieee802_1x_kay_set_latest_sa_attr(struct ieee802_1x_kay *kay,
   2558 				      struct ieee802_1x_mka_ki *lki, u8 lan,
   2559 				      Boolean ltx, Boolean lrx)
   2560 {
   2561 	struct ieee802_1x_mka_participant *principal;
   2562 
   2563 	principal = ieee802_1x_kay_get_principal_participant(kay);
   2564 	if (!principal)
   2565 		return -1;
   2566 
   2567 	if (!lki)
   2568 		os_memset(&principal->lki, 0, sizeof(principal->lki));
   2569 	else
   2570 		os_memcpy(&principal->lki, lki, sizeof(principal->lki));
   2571 
   2572 	principal->lan = lan;
   2573 	principal->ltx = ltx;
   2574 	principal->lrx = lrx;
   2575 	if (!lki) {
   2576 		kay->ltx_kn = 0;
   2577 		kay->lrx_kn = 0;
   2578 	} else {
   2579 		kay->ltx_kn = lki->kn;
   2580 		kay->lrx_kn = lki->kn;
   2581 	}
   2582 	kay->ltx_an = lan;
   2583 	kay->lrx_an = lan;
   2584 
   2585 	return 0;
   2586 }
   2587 
   2588 
   2589 /**
   2590  * ieee802_1x_kay_set_old_sa_attr -
   2591  */
   2592 int ieee802_1x_kay_set_old_sa_attr(struct ieee802_1x_kay *kay,
   2593 				   struct ieee802_1x_mka_ki *oki,
   2594 				   u8 oan, Boolean otx, Boolean orx)
   2595 {
   2596 	struct ieee802_1x_mka_participant *principal;
   2597 
   2598 	principal = ieee802_1x_kay_get_principal_participant(kay);
   2599 	if (!principal)
   2600 		return -1;
   2601 
   2602 	if (!oki)
   2603 		os_memset(&principal->oki, 0, sizeof(principal->oki));
   2604 	else
   2605 		os_memcpy(&principal->oki, oki, sizeof(principal->oki));
   2606 
   2607 	principal->oan = oan;
   2608 	principal->otx = otx;
   2609 	principal->orx = orx;
   2610 
   2611 	if (!oki) {
   2612 		kay->otx_kn = 0;
   2613 		kay->orx_kn = 0;
   2614 	} else {
   2615 		kay->otx_kn = oki->kn;
   2616 		kay->orx_kn = oki->kn;
   2617 	}
   2618 	kay->otx_an = oan;
   2619 	kay->orx_an = oan;
   2620 
   2621 	return 0;
   2622 }
   2623 
   2624 
   2625 static struct transmit_sa * lookup_txsa_by_an(struct transmit_sc *txsc, u8 an)
   2626 {
   2627 	struct transmit_sa *txsa;
   2628 
   2629 	dl_list_for_each(txsa, &txsc->sa_list, struct transmit_sa, list) {
   2630 		if (txsa->an == an)
   2631 			return txsa;
   2632 	}
   2633 
   2634 	return NULL;
   2635 }
   2636 
   2637 
   2638 static struct receive_sa * lookup_rxsa_by_an(struct receive_sc *rxsc, u8 an)
   2639 {
   2640 	struct receive_sa *rxsa;
   2641 
   2642 	dl_list_for_each(rxsa, &rxsc->sa_list, struct receive_sa, list) {
   2643 		if (rxsa->an == an)
   2644 			return rxsa;
   2645 	}
   2646 
   2647 	return NULL;
   2648 }
   2649 
   2650 
   2651 /**
   2652  * ieee802_1x_kay_create_sas -
   2653  */
   2654 int ieee802_1x_kay_create_sas(struct ieee802_1x_kay *kay,
   2655 			      struct ieee802_1x_mka_ki *lki)
   2656 {
   2657 	struct data_key *sa_key, *latest_sak;
   2658 	struct ieee802_1x_mka_participant *principal;
   2659 	struct receive_sc *rxsc;
   2660 	struct receive_sa *rxsa;
   2661 	struct transmit_sa *txsa;
   2662 
   2663 	principal = ieee802_1x_kay_get_principal_participant(kay);
   2664 	if (!principal)
   2665 		return -1;
   2666 
   2667 	latest_sak = NULL;
   2668 	dl_list_for_each(sa_key, &principal->sak_list, struct data_key, list) {
   2669 		if (is_ki_equal(&sa_key->key_identifier, lki)) {
   2670 			sa_key->rx_latest = TRUE;
   2671 			sa_key->tx_latest = TRUE;
   2672 			latest_sak = sa_key;
   2673 			principal->to_use_sak = TRUE;
   2674 		} else {
   2675 			sa_key->rx_latest = FALSE;
   2676 			sa_key->tx_latest = FALSE;
   2677 		}
   2678 	}
   2679 	if (!latest_sak) {
   2680 		wpa_printf(MSG_ERROR, "lki related sak not found");
   2681 		return -1;
   2682 	}
   2683 
   2684 	dl_list_for_each(rxsc, &principal->rxsc_list, struct receive_sc, list) {
   2685 		while ((rxsa = lookup_rxsa_by_an(rxsc, latest_sak->an)) != NULL)
   2686 			ieee802_1x_delete_receive_sa(kay, rxsa);
   2687 
   2688 		rxsa = ieee802_1x_kay_init_receive_sa(rxsc, latest_sak->an, 1,
   2689 						      latest_sak);
   2690 		if (!rxsa)
   2691 			return -1;
   2692 
   2693 		secy_create_receive_sa(kay, rxsa);
   2694 	}
   2695 
   2696 	while ((txsa = lookup_txsa_by_an(principal->txsc, latest_sak->an)) !=
   2697 	       NULL)
   2698 		ieee802_1x_delete_transmit_sa(kay, txsa);
   2699 
   2700 	txsa = ieee802_1x_kay_init_transmit_sa(principal->txsc, latest_sak->an,
   2701 					       1, latest_sak);
   2702 	if (!txsa)
   2703 		return -1;
   2704 
   2705 	secy_create_transmit_sa(kay, txsa);
   2706 
   2707 
   2708 
   2709 	return 0;
   2710 }
   2711 
   2712 
   2713 /**
   2714  * ieee802_1x_kay_delete_sas -
   2715  */
   2716 int ieee802_1x_kay_delete_sas(struct ieee802_1x_kay *kay,
   2717 			      struct ieee802_1x_mka_ki *ki)
   2718 {
   2719 	struct data_key *sa_key, *pre_key;
   2720 	struct transmit_sa *txsa, *pre_txsa;
   2721 	struct receive_sa *rxsa, *pre_rxsa;
   2722 	struct receive_sc *rxsc;
   2723 	struct ieee802_1x_mka_participant *principal;
   2724 
   2725 	wpa_printf(MSG_DEBUG, "KaY: Entry into %s", __func__);
   2726 	principal = ieee802_1x_kay_get_principal_participant(kay);
   2727 	if (!principal)
   2728 		return -1;
   2729 
   2730 	/* remove the transmit sa */
   2731 	dl_list_for_each_safe(txsa, pre_txsa, &principal->txsc->sa_list,
   2732 			      struct transmit_sa, list) {
   2733 		if (is_ki_equal(&txsa->pkey->key_identifier, ki))
   2734 			ieee802_1x_delete_transmit_sa(kay, txsa);
   2735 	}
   2736 
   2737 	/* remove the receive sa */
   2738 	dl_list_for_each(rxsc, &principal->rxsc_list, struct receive_sc, list) {
   2739 		dl_list_for_each_safe(rxsa, pre_rxsa, &rxsc->sa_list,
   2740 				      struct receive_sa, list) {
   2741 			if (is_ki_equal(&rxsa->pkey->key_identifier, ki))
   2742 				ieee802_1x_delete_receive_sa(kay, rxsa);
   2743 		}
   2744 	}
   2745 
   2746 	/* remove the sak */
   2747 	dl_list_for_each_safe(sa_key, pre_key, &principal->sak_list,
   2748 			      struct data_key, list) {
   2749 		if (is_ki_equal(&sa_key->key_identifier, ki)) {
   2750 			dl_list_del(&sa_key->list);
   2751 			ieee802_1x_kay_deinit_data_key(sa_key);
   2752 			break;
   2753 		}
   2754 		if (principal->new_key == sa_key)
   2755 			principal->new_key = NULL;
   2756 	}
   2757 
   2758 	return 0;
   2759 }
   2760 
   2761 
   2762 /**
   2763  * ieee802_1x_kay_enable_tx_sas -
   2764  */
   2765 int ieee802_1x_kay_enable_tx_sas(struct ieee802_1x_kay *kay,
   2766 				 struct ieee802_1x_mka_ki *lki)
   2767 {
   2768 	struct ieee802_1x_mka_participant *principal;
   2769 	struct transmit_sa *txsa;
   2770 
   2771 	principal = ieee802_1x_kay_get_principal_participant(kay);
   2772 	if (!principal)
   2773 		return -1;
   2774 
   2775 	dl_list_for_each(txsa, &principal->txsc->sa_list, struct transmit_sa,
   2776 			 list) {
   2777 		if (is_ki_equal(&txsa->pkey->key_identifier, lki)) {
   2778 			txsa->in_use = TRUE;
   2779 			secy_enable_transmit_sa(kay, txsa);
   2780 			ieee802_1x_cp_set_usingtransmitas(
   2781 				principal->kay->cp, TRUE);
   2782 			ieee802_1x_cp_sm_step(principal->kay->cp);
   2783 		}
   2784 	}
   2785 
   2786 	return 0;
   2787 }
   2788 
   2789 
   2790 /**
   2791  * ieee802_1x_kay_enable_rx_sas -
   2792  */
   2793 int ieee802_1x_kay_enable_rx_sas(struct ieee802_1x_kay *kay,
   2794 				 struct ieee802_1x_mka_ki *lki)
   2795 {
   2796 	struct ieee802_1x_mka_participant *principal;
   2797 	struct receive_sa *rxsa;
   2798 	struct receive_sc *rxsc;
   2799 
   2800 	principal = ieee802_1x_kay_get_principal_participant(kay);
   2801 	if (!principal)
   2802 		return -1;
   2803 
   2804 	dl_list_for_each(rxsc, &principal->rxsc_list, struct receive_sc, list) {
   2805 		dl_list_for_each(rxsa, &rxsc->sa_list, struct receive_sa, list)
   2806 		{
   2807 			if (is_ki_equal(&rxsa->pkey->key_identifier, lki)) {
   2808 				rxsa->in_use = TRUE;
   2809 				secy_enable_receive_sa(kay, rxsa);
   2810 				ieee802_1x_cp_set_usingreceivesas(
   2811 					principal->kay->cp, TRUE);
   2812 				ieee802_1x_cp_sm_step(principal->kay->cp);
   2813 			}
   2814 		}
   2815 	}
   2816 
   2817 	return 0;
   2818 }
   2819 
   2820 
   2821 /**
   2822  * ieee802_1x_kay_enable_new_info -
   2823  */
   2824 int ieee802_1x_kay_enable_new_info(struct ieee802_1x_kay *kay)
   2825 {
   2826 	struct ieee802_1x_mka_participant *principal;
   2827 
   2828 	principal = ieee802_1x_kay_get_principal_participant(kay);
   2829 	if (!principal)
   2830 		return -1;
   2831 
   2832 	if (principal->retry_count < MAX_RETRY_CNT || principal->mode == PSK) {
   2833 		ieee802_1x_participant_send_mkpdu(principal);
   2834 		principal->retry_count++;
   2835 	}
   2836 
   2837 	return 0;
   2838 }
   2839 
   2840 
   2841 /**
   2842  * ieee802_1x_kay_mkpdu_sanity_check -
   2843  *     sanity check specified in clause 11.11.2 of IEEE802.1X-2010
   2844  */
   2845 static int ieee802_1x_kay_mkpdu_sanity_check(struct ieee802_1x_kay *kay,
   2846 					     const u8 *buf, size_t len)
   2847 {
   2848 	struct ieee8023_hdr *eth_hdr;
   2849 	struct ieee802_1x_hdr *eapol_hdr;
   2850 	struct ieee802_1x_mka_hdr *mka_hdr;
   2851 	struct ieee802_1x_mka_basic_body *body;
   2852 	size_t mka_msg_len;
   2853 	struct ieee802_1x_mka_participant *participant;
   2854 	size_t body_len;
   2855 	u8 icv[MAX_ICV_LEN];
   2856 	u8 *msg_icv;
   2857 
   2858 	eth_hdr = (struct ieee8023_hdr *) buf;
   2859 	eapol_hdr = (struct ieee802_1x_hdr *) (eth_hdr + 1);
   2860 	mka_hdr = (struct ieee802_1x_mka_hdr *) (eapol_hdr + 1);
   2861 
   2862 	/* destination address should be not individual address */
   2863 	if (os_memcmp(eth_hdr->dest, pae_group_addr, ETH_ALEN) != 0) {
   2864 		wpa_printf(MSG_MSGDUMP,
   2865 			   "KaY: ethernet destination address is not PAE group address");
   2866 		return -1;
   2867 	}
   2868 
   2869 	/* MKPDU should not be less than 32 octets */
   2870 	mka_msg_len = be_to_host16(eapol_hdr->length);
   2871 	if (mka_msg_len < 32) {
   2872 		wpa_printf(MSG_MSGDUMP, "KaY: MKPDU is less than 32 octets");
   2873 		return -1;
   2874 	}
   2875 	/* MKPDU should be a multiple of 4 octets */
   2876 	if ((mka_msg_len % 4) != 0) {
   2877 		wpa_printf(MSG_MSGDUMP,
   2878 			   "KaY: MKPDU is not multiple of 4 octets");
   2879 		return -1;
   2880 	}
   2881 
   2882 	body = (struct ieee802_1x_mka_basic_body *) mka_hdr;
   2883 	ieee802_1x_mka_dump_basic_body(body);
   2884 	body_len = get_mka_param_body_len(body);
   2885 	/* EAPOL-MKA body should comprise basic parameter set and ICV */
   2886 	if (mka_msg_len < MKA_HDR_LEN + body_len + DEFAULT_ICV_LEN) {
   2887 		wpa_printf(MSG_ERROR,
   2888 			   "KaY: Received EAPOL-MKA Packet Body Length (%zu bytes) is less than the Basic Parameter Set Header Length (%zu bytes) + the Basic Parameter Set Body Length (%zu bytes) + %d bytes of ICV",
   2889 			   mka_msg_len, MKA_HDR_LEN,
   2890 			   body_len, DEFAULT_ICV_LEN);
   2891 		return -1;
   2892 	}
   2893 
   2894 	/* CKN should be owned by I */
   2895 	participant = ieee802_1x_kay_get_participant(kay, body->ckn);
   2896 	if (!participant) {
   2897 		wpa_printf(MSG_DEBUG, "CKN is not included in my CA");
   2898 		return -1;
   2899 	}
   2900 
   2901 	/* algorithm agility check */
   2902 	if (os_memcmp(body->algo_agility, mka_algo_agility,
   2903 		      sizeof(body->algo_agility)) != 0) {
   2904 		wpa_printf(MSG_ERROR,
   2905 			   "KaY: peer's algorithm agility not supported for me");
   2906 		return -1;
   2907 	}
   2908 
   2909 	/* ICV check */
   2910 	/*
   2911 	 * The ICV will comprise the final octets of the packet body, whatever
   2912 	 * its size, not the fixed length 16 octets, indicated by the EAPOL
   2913 	 * packet body length.
   2914 	 */
   2915 	if (mka_alg_tbl[kay->mka_algindex].icv_hash(
   2916 		    participant->ick.key,
   2917 		    buf, len - mka_alg_tbl[kay->mka_algindex].icv_len, icv)) {
   2918 		wpa_printf(MSG_ERROR, "KaY: omac1_aes_128 failed");
   2919 		return -1;
   2920 	}
   2921 
   2922 	msg_icv = ieee802_1x_mka_decode_icv_body(participant, (u8 *) mka_hdr,
   2923 						 mka_msg_len);
   2924 	if (!msg_icv) {
   2925 		wpa_printf(MSG_ERROR, "KaY: No ICV");
   2926 		return -1;
   2927 	}
   2928 	if (os_memcmp_const(msg_icv, icv,
   2929 			    mka_alg_tbl[kay->mka_algindex].icv_len) != 0) {
   2930 		wpa_printf(MSG_ERROR,
   2931 			   "KaY: Computed ICV is not equal to Received ICV");
   2932 		return -1;
   2933 	}
   2934 
   2935 	return 0;
   2936 }
   2937 
   2938 
   2939 /**
   2940  * ieee802_1x_kay_decode_mkpdu -
   2941  */
   2942 static int ieee802_1x_kay_decode_mkpdu(struct ieee802_1x_kay *kay,
   2943 				       const u8 *buf, size_t len)
   2944 {
   2945 	struct ieee802_1x_mka_participant *participant;
   2946 	struct ieee802_1x_mka_hdr *hdr;
   2947 	size_t body_len;
   2948 	size_t left_len;
   2949 	u8 body_type;
   2950 	int i;
   2951 	const u8 *pos;
   2952 	Boolean handled[256];
   2953 
   2954 	if (ieee802_1x_kay_mkpdu_sanity_check(kay, buf, len))
   2955 		return -1;
   2956 
   2957 	/* handle basic parameter set */
   2958 	pos = buf + sizeof(struct ieee8023_hdr) + sizeof(struct ieee802_1x_hdr);
   2959 	left_len = len - sizeof(struct ieee8023_hdr) -
   2960 		sizeof(struct ieee802_1x_hdr);
   2961 	participant = ieee802_1x_mka_decode_basic_body(kay, pos, left_len);
   2962 	if (!participant)
   2963 		return -1;
   2964 
   2965 	/* to skip basic parameter set */
   2966 	hdr = (struct ieee802_1x_mka_hdr *) pos;
   2967 	body_len = get_mka_param_body_len(hdr);
   2968 	pos += body_len + MKA_HDR_LEN;
   2969 	left_len -= body_len + MKA_HDR_LEN;
   2970 
   2971 	/* check i am in the peer's peer list */
   2972 	if (ieee802_1x_mka_i_in_peerlist(participant, pos, left_len) &&
   2973 	    !ieee802_1x_kay_is_in_live_peer(participant,
   2974 					    participant->current_peer_id.mi)) {
   2975 		/* accept the peer as live peer */
   2976 		if (ieee802_1x_kay_is_in_potential_peer(
   2977 			    participant, participant->current_peer_id.mi)) {
   2978 			if (!ieee802_1x_kay_move_live_peer(
   2979 				    participant,
   2980 				    participant->current_peer_id.mi,
   2981 				    be_to_host32(participant->
   2982 						 current_peer_id.mn)))
   2983 				return -1;
   2984 		} else if (!ieee802_1x_kay_create_live_peer(
   2985 				   participant, participant->current_peer_id.mi,
   2986 				   be_to_host32(participant->
   2987 						current_peer_id.mn))) {
   2988 				return -1;
   2989 		}
   2990 
   2991 		ieee802_1x_kay_elect_key_server(participant);
   2992 		ieee802_1x_kay_decide_macsec_use(participant);
   2993 	}
   2994 
   2995 	/*
   2996 	 * Handle other parameter set than basic parameter set.
   2997 	 * Each parameter set should be present only once.
   2998 	 */
   2999 	for (i = 0; i < 256; i++)
   3000 		handled[i] = FALSE;
   3001 
   3002 	handled[0] = TRUE;
   3003 	for (; left_len > MKA_HDR_LEN + DEFAULT_ICV_LEN;
   3004 	     pos += body_len + MKA_HDR_LEN,
   3005 		     left_len -= body_len + MKA_HDR_LEN) {
   3006 		hdr = (struct ieee802_1x_mka_hdr *) pos;
   3007 		body_len = get_mka_param_body_len(hdr);
   3008 		body_type = get_mka_param_body_type(hdr);
   3009 
   3010 		if (body_type == MKA_ICV_INDICATOR)
   3011 			return 0;
   3012 
   3013 		if (left_len < (MKA_HDR_LEN + body_len + DEFAULT_ICV_LEN)) {
   3014 			wpa_printf(MSG_ERROR,
   3015 				   "KaY: MKA Peer Packet Body Length (%zu bytes) is less than the Parameter Set Header Length (%zu bytes) + the Parameter Set Body Length (%zu bytes) + %d bytes of ICV",
   3016 				   left_len, MKA_HDR_LEN,
   3017 				   body_len, DEFAULT_ICV_LEN);
   3018 			continue;
   3019 		}
   3020 
   3021 		if (handled[body_type])
   3022 			continue;
   3023 
   3024 		handled[body_type] = TRUE;
   3025 		if (body_type < ARRAY_SIZE(mka_body_handler) &&
   3026 		    mka_body_handler[body_type].body_rx) {
   3027 			mka_body_handler[body_type].body_rx
   3028 				(participant, pos, left_len);
   3029 		} else {
   3030 			wpa_printf(MSG_ERROR,
   3031 				   "The type %d is not supported in this MKA version %d",
   3032 				   body_type, MKA_VERSION_ID);
   3033 		}
   3034 	}
   3035 
   3036 	kay->active = TRUE;
   3037 	participant->retry_count = 0;
   3038 	participant->active = TRUE;
   3039 
   3040 	return 0;
   3041 }
   3042 
   3043 
   3044 
   3045 static void kay_l2_receive(void *ctx, const u8 *src_addr, const u8 *buf,
   3046 			   size_t len)
   3047 {
   3048 	struct ieee802_1x_kay *kay = ctx;
   3049 	struct ieee8023_hdr *eth_hdr;
   3050 	struct ieee802_1x_hdr *eapol_hdr;
   3051 
   3052 	/* must contain at least ieee8023_hdr + ieee802_1x_hdr */
   3053 	if (len < sizeof(*eth_hdr) + sizeof(*eapol_hdr)) {
   3054 		wpa_printf(MSG_MSGDUMP, "KaY: EAPOL frame too short (%lu)",
   3055 			   (unsigned long) len);
   3056 		return;
   3057 	}
   3058 
   3059 	eth_hdr = (struct ieee8023_hdr *) buf;
   3060 	eapol_hdr = (struct ieee802_1x_hdr *) (eth_hdr + 1);
   3061 	if (len != sizeof(*eth_hdr) + sizeof(*eapol_hdr) +
   3062 	    be_to_host16(eapol_hdr->length)) {
   3063 		wpa_printf(MSG_MSGDUMP, "KAY: EAPOL MPDU is invalid: (%lu-%lu)",
   3064 			   (unsigned long) len,
   3065 			   (unsigned long) be_to_host16(eapol_hdr->length));
   3066 		return;
   3067 	}
   3068 
   3069 	if (eapol_hdr->version < EAPOL_VERSION) {
   3070 		wpa_printf(MSG_MSGDUMP, "KaY: version %d does not support MKA",
   3071 			   eapol_hdr->version);
   3072 		return;
   3073 	}
   3074 	if (be_to_host16(eth_hdr->ethertype) != ETH_P_PAE ||
   3075 	    eapol_hdr->type != IEEE802_1X_TYPE_EAPOL_MKA)
   3076 		return;
   3077 
   3078 	wpa_hexdump(MSG_DEBUG, "RX EAPOL-MKA: ", buf, len);
   3079 	if (dl_list_empty(&kay->participant_list)) {
   3080 		wpa_printf(MSG_ERROR, "KaY: no MKA participant instance");
   3081 		return;
   3082 	}
   3083 
   3084 	ieee802_1x_kay_decode_mkpdu(kay, buf, len);
   3085 }
   3086 
   3087 
   3088 /**
   3089  * ieee802_1x_kay_init -
   3090  */
   3091 struct ieee802_1x_kay *
   3092 ieee802_1x_kay_init(struct ieee802_1x_kay_ctx *ctx, enum macsec_policy policy,
   3093 		    u16 port, u8 priority, const char *ifname, const u8 *addr)
   3094 {
   3095 	struct ieee802_1x_kay *kay;
   3096 
   3097 	kay = os_zalloc(sizeof(*kay));
   3098 	if (!kay) {
   3099 		wpa_printf(MSG_ERROR, "KaY-%s: out of memory", __func__);
   3100 		return NULL;
   3101 	}
   3102 
   3103 	kay->ctx = ctx;
   3104 
   3105 	kay->enable = TRUE;
   3106 	kay->active = FALSE;
   3107 
   3108 	kay->authenticated = FALSE;
   3109 	kay->secured = FALSE;
   3110 	kay->failed = FALSE;
   3111 	kay->policy = policy;
   3112 
   3113 	os_strlcpy(kay->if_name, ifname, IFNAMSIZ);
   3114 	os_memcpy(kay->actor_sci.addr, addr, ETH_ALEN);
   3115 	kay->actor_sci.port = host_to_be16(port ? port : 0x0001);
   3116 	kay->actor_priority = priority;
   3117 
   3118 	/* While actor acts as a key server, shall distribute sakey */
   3119 	kay->dist_kn = 1;
   3120 	kay->dist_an = 0;
   3121 	kay->dist_time = 0;
   3122 
   3123 	kay->pn_exhaustion = PENDING_PN_EXHAUSTION;
   3124 	kay->macsec_csindex = DEFAULT_CS_INDEX;
   3125 	kay->mka_algindex = DEFAULT_MKA_ALG_INDEX;
   3126 	kay->mka_version = MKA_VERSION_ID;
   3127 
   3128 	os_memcpy(kay->algo_agility, mka_algo_agility,
   3129 		  sizeof(kay->algo_agility));
   3130 
   3131 	dl_list_init(&kay->participant_list);
   3132 
   3133 	if (policy != DO_NOT_SECURE &&
   3134 	    secy_get_capability(kay, &kay->macsec_capable) < 0) {
   3135 		os_free(kay);
   3136 		return NULL;
   3137 	}
   3138 
   3139 	if (policy == DO_NOT_SECURE ||
   3140 	    kay->macsec_capable == MACSEC_CAP_NOT_IMPLEMENTED) {
   3141 		kay->macsec_capable = MACSEC_CAP_NOT_IMPLEMENTED;
   3142 		kay->macsec_desired = FALSE;
   3143 		kay->macsec_protect = FALSE;
   3144 		kay->macsec_validate = Disabled;
   3145 		kay->macsec_replay_protect = FALSE;
   3146 		kay->macsec_replay_window = 0;
   3147 		kay->macsec_confidentiality = CONFIDENTIALITY_NONE;
   3148 	} else {
   3149 		kay->macsec_desired = TRUE;
   3150 		kay->macsec_protect = TRUE;
   3151 		kay->macsec_encrypt = policy == SHOULD_ENCRYPT;
   3152 		kay->macsec_validate = Strict;
   3153 		kay->macsec_replay_protect = FALSE;
   3154 		kay->macsec_replay_window = 0;
   3155 		if (kay->macsec_capable >= MACSEC_CAP_INTEG_AND_CONF)
   3156 			kay->macsec_confidentiality = CONFIDENTIALITY_OFFSET_0;
   3157 		else
   3158 			kay->macsec_confidentiality = CONFIDENTIALITY_NONE;
   3159 	}
   3160 
   3161 	wpa_printf(MSG_DEBUG, "KaY: state machine created");
   3162 
   3163 	/* Initialize the SecY must be prio to CP, as CP will control SecY */
   3164 	secy_init_macsec(kay);
   3165 
   3166 	wpa_printf(MSG_DEBUG, "KaY: secy init macsec done");
   3167 
   3168 	/* init CP */
   3169 	kay->cp = ieee802_1x_cp_sm_init(kay);
   3170 	if (kay->cp == NULL) {
   3171 		ieee802_1x_kay_deinit(kay);
   3172 		return NULL;
   3173 	}
   3174 
   3175 	if (policy == DO_NOT_SECURE) {
   3176 		ieee802_1x_cp_connect_authenticated(kay->cp);
   3177 		ieee802_1x_cp_sm_step(kay->cp);
   3178 	} else {
   3179 		kay->l2_mka = l2_packet_init(kay->if_name, NULL, ETH_P_PAE,
   3180 					     kay_l2_receive, kay, 1);
   3181 		if (kay->l2_mka == NULL) {
   3182 			wpa_printf(MSG_WARNING,
   3183 				   "KaY: Failed to initialize L2 packet processing for MKA packet");
   3184 			ieee802_1x_kay_deinit(kay);
   3185 			return NULL;
   3186 		}
   3187 	}
   3188 
   3189 	return kay;
   3190 }
   3191 
   3192 
   3193 /**
   3194  * ieee802_1x_kay_deinit -
   3195  */
   3196 void
   3197 ieee802_1x_kay_deinit(struct ieee802_1x_kay *kay)
   3198 {
   3199 	struct ieee802_1x_mka_participant *participant;
   3200 
   3201 	if (!kay)
   3202 		return;
   3203 
   3204 	wpa_printf(MSG_DEBUG, "KaY: state machine removed");
   3205 
   3206 	while (!dl_list_empty(&kay->participant_list)) {
   3207 		participant = dl_list_entry(kay->participant_list.next,
   3208 					    struct ieee802_1x_mka_participant,
   3209 					    list);
   3210 		ieee802_1x_kay_delete_mka(kay, &participant->ckn);
   3211 	}
   3212 
   3213 	ieee802_1x_cp_sm_deinit(kay->cp);
   3214 	secy_deinit_macsec(kay);
   3215 
   3216 	if (kay->l2_mka) {
   3217 		l2_packet_deinit(kay->l2_mka);
   3218 		kay->l2_mka = NULL;
   3219 	}
   3220 
   3221 	os_free(kay->ctx);
   3222 	os_free(kay);
   3223 }
   3224 
   3225 
   3226 /**
   3227  * ieee802_1x_kay_create_mka -
   3228  */
   3229 struct ieee802_1x_mka_participant *
   3230 ieee802_1x_kay_create_mka(struct ieee802_1x_kay *kay, struct mka_key_name *ckn,
   3231 			  struct mka_key *cak, u32 life,
   3232 			  enum mka_created_mode mode, Boolean is_authenticator)
   3233 {
   3234 	struct ieee802_1x_mka_participant *participant;
   3235 	unsigned int usecs;
   3236 
   3237 	if (!kay || !ckn || !cak) {
   3238 		wpa_printf(MSG_ERROR, "KaY: ckn or cak is null");
   3239 		return NULL;
   3240 	}
   3241 
   3242 	if (cak->len != mka_alg_tbl[kay->mka_algindex].cak_len) {
   3243 		wpa_printf(MSG_ERROR, "KaY: CAK length not follow key schema");
   3244 		return NULL;
   3245 	}
   3246 	if (ckn->len > MAX_CKN_LEN) {
   3247 		wpa_printf(MSG_ERROR, "KaY: CKN is out of range(<=32 bytes)");
   3248 		return NULL;
   3249 	}
   3250 	if (!kay->enable) {
   3251 		wpa_printf(MSG_ERROR, "KaY: Now is at disable state");
   3252 		return NULL;
   3253 	}
   3254 
   3255 	participant = os_zalloc(sizeof(*participant));
   3256 	if (!participant) {
   3257 		wpa_printf(MSG_ERROR, "KaY-%s: out of memory", __func__);
   3258 		return NULL;
   3259 	}
   3260 
   3261 	participant->ckn.len = ckn->len;
   3262 	os_memcpy(participant->ckn.name, ckn->name, ckn->len);
   3263 	participant->cak.len = cak->len;
   3264 	os_memcpy(participant->cak.key, cak->key, cak->len);
   3265 	if (life)
   3266 		participant->cak_life = life + time(NULL);
   3267 
   3268 	switch (mode) {
   3269 	case EAP_EXCHANGE:
   3270 		if (is_authenticator) {
   3271 			participant->is_obliged_key_server = TRUE;
   3272 			participant->can_be_key_server = TRUE;
   3273 			participant->is_key_server = TRUE;
   3274 			participant->principal = TRUE;
   3275 
   3276 			os_memcpy(&kay->key_server_sci, &kay->actor_sci,
   3277 				  sizeof(kay->key_server_sci));
   3278 			kay->key_server_priority = kay->actor_priority;
   3279 			participant->is_elected = TRUE;
   3280 		} else {
   3281 			participant->is_obliged_key_server = FALSE;
   3282 			participant->can_be_key_server = FALSE;
   3283 			participant->is_key_server = FALSE;
   3284 			participant->is_elected = TRUE;
   3285 		}
   3286 		break;
   3287 
   3288 	default:
   3289 		participant->is_obliged_key_server = FALSE;
   3290 		participant->can_be_key_server = TRUE;
   3291 		participant->is_key_server = TRUE;
   3292 		participant->is_elected = FALSE;
   3293 		break;
   3294 	}
   3295 
   3296 	participant->cached = FALSE;
   3297 
   3298 	participant->active = FALSE;
   3299 	participant->participant = FALSE;
   3300 	participant->retain = FALSE;
   3301 	participant->activate = DEFAULT;
   3302 
   3303 	if (participant->is_key_server)
   3304 		participant->principal = TRUE;
   3305 
   3306 	dl_list_init(&participant->live_peers);
   3307 	dl_list_init(&participant->potential_peers);
   3308 
   3309 	participant->retry_count = 0;
   3310 	participant->kay = kay;
   3311 
   3312 	if (!reset_participant_mi(participant))
   3313 		goto fail;
   3314 
   3315 	participant->lrx = FALSE;
   3316 	participant->ltx = FALSE;
   3317 	participant->orx = FALSE;
   3318 	participant->otx = FALSE;
   3319 	participant->to_dist_sak = FALSE;
   3320 	participant->to_use_sak = FALSE;
   3321 	participant->new_sak = FALSE;
   3322 	dl_list_init(&participant->sak_list);
   3323 	participant->new_key = NULL;
   3324 	dl_list_init(&participant->rxsc_list);
   3325 	participant->txsc = ieee802_1x_kay_init_transmit_sc(&kay->actor_sci);
   3326 	secy_cp_control_protect_frames(kay, kay->macsec_protect);
   3327 	secy_cp_control_replay(kay, kay->macsec_replay_protect,
   3328 			       kay->macsec_replay_window);
   3329 	secy_create_transmit_sc(kay, participant->txsc);
   3330 
   3331 	/* to derive KEK from CAK and CKN */
   3332 	participant->kek.len = mka_alg_tbl[kay->mka_algindex].kek_len;
   3333 	if (mka_alg_tbl[kay->mka_algindex].kek_trfm(participant->cak.key,
   3334 						    participant->ckn.name,
   3335 						    participant->ckn.len,
   3336 						    participant->kek.key)) {
   3337 		wpa_printf(MSG_ERROR, "KaY: Derived KEK failed");
   3338 		goto fail;
   3339 	}
   3340 	wpa_hexdump_key(MSG_DEBUG, "KaY: Derived KEK",
   3341 			participant->kek.key, participant->kek.len);
   3342 
   3343 	/* to derive ICK from CAK and CKN */
   3344 	participant->ick.len = mka_alg_tbl[kay->mka_algindex].ick_len;
   3345 	if (mka_alg_tbl[kay->mka_algindex].ick_trfm(participant->cak.key,
   3346 						    participant->ckn.name,
   3347 						    participant->ckn.len,
   3348 						    participant->ick.key)) {
   3349 		wpa_printf(MSG_ERROR, "KaY: Derived ICK failed");
   3350 		goto fail;
   3351 	}
   3352 	wpa_hexdump_key(MSG_DEBUG, "KaY: Derived ICK",
   3353 			participant->ick.key, participant->ick.len);
   3354 
   3355 	dl_list_add(&kay->participant_list, &participant->list);
   3356 	wpa_hexdump(MSG_DEBUG, "KaY: Participant created:",
   3357 		    ckn->name, ckn->len);
   3358 
   3359 	usecs = os_random() % (MKA_HELLO_TIME * 1000);
   3360 	eloop_register_timeout(0, usecs, ieee802_1x_participant_timer,
   3361 			       participant, NULL);
   3362 
   3363 	/* Disable MKA lifetime for PSK mode.
   3364 	 * The peer(s) can take a long time to come up, because we
   3365 	 * create a "standby" MKA, and we need it to remain live until
   3366 	 * some peer appears.
   3367 	 */
   3368 	if (mode != PSK) {
   3369 		participant->mka_life = MKA_LIFE_TIME / 1000 + time(NULL) +
   3370 			usecs / 1000000;
   3371 	}
   3372 	participant->mode = mode;
   3373 
   3374 	return participant;
   3375 
   3376 fail:
   3377 	os_free(participant);
   3378 	return NULL;
   3379 }
   3380 
   3381 
   3382 /**
   3383  * ieee802_1x_kay_delete_mka -
   3384  */
   3385 void
   3386 ieee802_1x_kay_delete_mka(struct ieee802_1x_kay *kay, struct mka_key_name *ckn)
   3387 {
   3388 	struct ieee802_1x_mka_participant *participant;
   3389 	struct ieee802_1x_kay_peer *peer;
   3390 	struct data_key *sak;
   3391 	struct receive_sc *rxsc;
   3392 
   3393 	if (!kay || !ckn)
   3394 		return;
   3395 
   3396 	wpa_printf(MSG_DEBUG, "KaY: participant removed");
   3397 
   3398 	/* get the participant */
   3399 	participant = ieee802_1x_kay_get_participant(kay, ckn->name);
   3400 	if (!participant) {
   3401 		wpa_hexdump(MSG_DEBUG, "KaY: participant is not found",
   3402 			    ckn->name, ckn->len);
   3403 		return;
   3404 	}
   3405 
   3406 	eloop_cancel_timeout(ieee802_1x_participant_timer, participant, NULL);
   3407 	dl_list_del(&participant->list);
   3408 
   3409 	/* remove live peer */
   3410 	while (!dl_list_empty(&participant->live_peers)) {
   3411 		peer = dl_list_entry(participant->live_peers.next,
   3412 				     struct ieee802_1x_kay_peer, list);
   3413 		dl_list_del(&peer->list);
   3414 		os_free(peer);
   3415 	}
   3416 
   3417 	/* remove potential peer */
   3418 	while (!dl_list_empty(&participant->potential_peers)) {
   3419 		peer = dl_list_entry(participant->potential_peers.next,
   3420 				     struct ieee802_1x_kay_peer, list);
   3421 		dl_list_del(&peer->list);
   3422 		os_free(peer);
   3423 	}
   3424 
   3425 	/* remove sak */
   3426 	while (!dl_list_empty(&participant->sak_list)) {
   3427 		sak = dl_list_entry(participant->sak_list.next,
   3428 				    struct data_key, list);
   3429 		dl_list_del(&sak->list);
   3430 		ieee802_1x_kay_deinit_data_key(sak);
   3431 	}
   3432 	while (!dl_list_empty(&participant->rxsc_list)) {
   3433 		rxsc = dl_list_entry(participant->rxsc_list.next,
   3434 				     struct receive_sc, list);
   3435 		ieee802_1x_kay_deinit_receive_sc(participant, rxsc);
   3436 		secy_delete_receive_sc(kay, rxsc);
   3437 	}
   3438 	ieee802_1x_kay_deinit_transmit_sc(participant, participant->txsc);
   3439 	secy_delete_transmit_sc(kay, participant->txsc);
   3440 
   3441 	os_memset(&participant->cak, 0, sizeof(participant->cak));
   3442 	os_memset(&participant->kek, 0, sizeof(participant->kek));
   3443 	os_memset(&participant->ick, 0, sizeof(participant->ick));
   3444 	os_free(participant);
   3445 }
   3446 
   3447 
   3448 /**
   3449  * ieee802_1x_kay_mka_participate -
   3450  */
   3451 void ieee802_1x_kay_mka_participate(struct ieee802_1x_kay *kay,
   3452 				    struct mka_key_name *ckn,
   3453 				    Boolean status)
   3454 {
   3455 	struct ieee802_1x_mka_participant *participant;
   3456 
   3457 	if (!kay || !ckn)
   3458 		return;
   3459 
   3460 	participant = ieee802_1x_kay_get_participant(kay, ckn->name);
   3461 	if (!participant)
   3462 		return;
   3463 
   3464 	participant->active = status;
   3465 }
   3466 
   3467 
   3468 /**
   3469  * ieee802_1x_kay_new_sak -
   3470  */
   3471 int
   3472 ieee802_1x_kay_new_sak(struct ieee802_1x_kay *kay)
   3473 {
   3474 	struct ieee802_1x_mka_participant *participant;
   3475 
   3476 	if (!kay)
   3477 		return -1;
   3478 
   3479 	participant = ieee802_1x_kay_get_principal_participant(kay);
   3480 	if (!participant)
   3481 		return -1;
   3482 
   3483 	participant->new_sak = TRUE;
   3484 	wpa_printf(MSG_DEBUG, "KaY: new SAK signal");
   3485 
   3486 	return 0;
   3487 }
   3488 
   3489 
   3490 /**
   3491  * ieee802_1x_kay_change_cipher_suite -
   3492  */
   3493 int
   3494 ieee802_1x_kay_change_cipher_suite(struct ieee802_1x_kay *kay,
   3495 				   unsigned int cs_index)
   3496 {
   3497 	struct ieee802_1x_mka_participant *participant;
   3498 	enum macsec_cap secy_cap;
   3499 
   3500 	if (!kay)
   3501 		return -1;
   3502 
   3503 	if (cs_index >= CS_TABLE_SIZE) {
   3504 		wpa_printf(MSG_ERROR,
   3505 			   "KaY: Configured cipher suite index is out of range");
   3506 		return -1;
   3507 	}
   3508 	if (kay->macsec_csindex == cs_index)
   3509 		return -2;
   3510 
   3511 	if (cs_index == 0)
   3512 		kay->macsec_desired = FALSE;
   3513 
   3514 	kay->macsec_csindex = cs_index;
   3515 	kay->macsec_capable = cipher_suite_tbl[kay->macsec_csindex].capable;
   3516 
   3517 	if (secy_get_capability(kay, &secy_cap) < 0)
   3518 		return -3;
   3519 
   3520 	if (kay->macsec_capable > secy_cap)
   3521 		kay->macsec_capable = secy_cap;
   3522 
   3523 	participant = ieee802_1x_kay_get_principal_participant(kay);
   3524 	if (participant) {
   3525 		wpa_printf(MSG_INFO, "KaY: Cipher Suite changed");
   3526 		participant->new_sak = TRUE;
   3527 	}
   3528 
   3529 	return 0;
   3530 }
   3531 
   3532 
   3533 #ifdef CONFIG_CTRL_IFACE
   3534 /**
   3535  * ieee802_1x_kay_get_status - Get IEEE 802.1X KaY status details
   3536  * @sm: Pointer to KaY allocated with ieee802_1x_kay_init()
   3537  * @buf: Buffer for status information
   3538  * @buflen: Maximum buffer length
   3539  * @verbose: Whether to include verbose status information
   3540  * Returns: Number of bytes written to buf.
   3541  *
   3542  * Query KAY status information. This function fills in a text area with current
   3543  * status information. If the buffer (buf) is not large enough, status
   3544  * information will be truncated to fit the buffer.
   3545  */
   3546 int ieee802_1x_kay_get_status(struct ieee802_1x_kay *kay, char *buf,
   3547 			      size_t buflen)
   3548 {
   3549 	int len;
   3550 
   3551 	if (!kay)
   3552 		return 0;
   3553 
   3554 	len = os_snprintf(buf, buflen,
   3555 			  "PAE KaY status=%s\n"
   3556 			  "Authenticated=%s\n"
   3557 			  "Secured=%s\n"
   3558 			  "Failed=%s\n"
   3559 			  "Actor Priority=%u\n"
   3560 			  "Key Server Priority=%u\n"
   3561 			  "Is Key Server=%s\n"
   3562 			  "Number of Keys Distributed=%u\n"
   3563 			  "Number of Keys Received=%u\n",
   3564 			  kay->active ? "Active" : "Not-Active",
   3565 			  kay->authenticated ? "Yes" : "No",
   3566 			  kay->secured ? "Yes" : "No",
   3567 			  kay->failed ? "Yes" : "No",
   3568 			  kay->actor_priority,
   3569 			  kay->key_server_priority,
   3570 			  kay->is_key_server ? "Yes" : "No",
   3571 			  kay->dist_kn - 1,
   3572 			  kay->rcvd_keys);
   3573 	if (os_snprintf_error(buflen, len))
   3574 		return 0;
   3575 
   3576 	return len;
   3577 }
   3578 #endif /* CONFIG_CTRL_IFACE */
   3579