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