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