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