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