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