• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 	return 0;
1839 }
1840 
1841 
1842 /**
1843  * ieee802_1x_mka_icv_body_present
1844  */
1845 static bool
ieee802_1x_mka_icv_body_present(struct ieee802_1x_mka_participant * participant)1846 ieee802_1x_mka_icv_body_present(struct ieee802_1x_mka_participant *participant)
1847 {
1848 	return true;
1849 }
1850 
1851 
1852 /**
1853  * ieee802_1x_kay_get_icv_length
1854  */
1855 static int
ieee802_1x_mka_get_icv_length(struct ieee802_1x_mka_participant * participant)1856 ieee802_1x_mka_get_icv_length(struct ieee802_1x_mka_participant *participant)
1857 {
1858 	int length;
1859 
1860 	/* Determine if we need space for the ICV Indicator */
1861 	if (mka_alg_tbl[participant->kay->mka_algindex].icv_len !=
1862 	    DEFAULT_ICV_LEN)
1863 		length = sizeof(struct ieee802_1x_mka_icv_body);
1864 	else
1865 		length = 0;
1866 	length += mka_alg_tbl[participant->kay->mka_algindex].icv_len;
1867 
1868 	return MKA_ALIGN_LENGTH(length);
1869 }
1870 
1871 
1872 /**
1873  * ieee802_1x_mka_encode_icv_body -
1874  */
1875 static int
ieee802_1x_mka_encode_icv_body(struct ieee802_1x_mka_participant * participant,struct wpabuf * buf)1876 ieee802_1x_mka_encode_icv_body(struct ieee802_1x_mka_participant *participant,
1877 			       struct wpabuf *buf)
1878 {
1879 	struct ieee802_1x_mka_icv_body *body;
1880 	unsigned int length;
1881 	u8 cmac[MAX_ICV_LEN];
1882 
1883 	length = ieee802_1x_mka_get_icv_length(participant);
1884 	if (mka_alg_tbl[participant->kay->mka_algindex].icv_len !=
1885 	    DEFAULT_ICV_LEN)  {
1886 		wpa_printf(MSG_DEBUG, "KaY: ICV Indicator");
1887 		body = wpabuf_put(buf, MKA_HDR_LEN);
1888 		body->type = MKA_ICV_INDICATOR;
1889 		length -= MKA_HDR_LEN;
1890 		set_mka_param_body_len(body, length);
1891 	}
1892 
1893 	if (mka_alg_tbl[participant->kay->mka_algindex].icv_hash(
1894 		    participant->ick.key, participant->ick.len,
1895 		    wpabuf_head(buf), wpabuf_len(buf), cmac)) {
1896 		wpa_printf(MSG_ERROR, "KaY: failed to calculate ICV");
1897 		return -1;
1898 	}
1899 	wpa_hexdump(MSG_DEBUG, "KaY: ICV", cmac, length);
1900 
1901 	os_memcpy(wpabuf_put(buf, length), cmac, length);
1902 
1903 	return 0;
1904 }
1905 
1906 /**
1907  * ieee802_1x_mka_decode_icv_body -
1908  */
1909 static const u8 *
ieee802_1x_mka_decode_icv_body(struct ieee802_1x_mka_participant * participant,const u8 * mka_msg,size_t msg_len)1910 ieee802_1x_mka_decode_icv_body(struct ieee802_1x_mka_participant *participant,
1911 			       const u8 *mka_msg, size_t msg_len)
1912 {
1913 	const struct ieee802_1x_mka_hdr *hdr;
1914 	const struct ieee802_1x_mka_icv_body *body;
1915 	size_t body_len;
1916 	size_t left_len;
1917 	u8 body_type;
1918 	const u8 *pos;
1919 
1920 	pos = mka_msg;
1921 	left_len = msg_len;
1922 	while (left_len > MKA_HDR_LEN + DEFAULT_ICV_LEN) {
1923 		hdr = (const struct ieee802_1x_mka_hdr *) pos;
1924 		body_len = MKA_ALIGN_LENGTH(get_mka_param_body_len(hdr));
1925 		body_type = get_mka_param_body_type(hdr);
1926 
1927 		if (left_len < body_len + MKA_HDR_LEN)
1928 			break;
1929 
1930 		if (body_type != MKA_ICV_INDICATOR) {
1931 			left_len -= MKA_HDR_LEN + body_len;
1932 			pos += MKA_HDR_LEN + body_len;
1933 			continue;
1934 		}
1935 
1936 		body = (const struct ieee802_1x_mka_icv_body *) pos;
1937 		if (body_len
1938 		    < mka_alg_tbl[participant->kay->mka_algindex].icv_len)
1939 			return NULL;
1940 
1941 		return body->icv;
1942 	}
1943 
1944 	return mka_msg + msg_len - DEFAULT_ICV_LEN;
1945 }
1946 
1947 
1948 /**
1949  * ieee802_1x_mka_decode_dist_cak_body-
1950  */
1951 static int
ieee802_1x_mka_decode_dist_cak_body(struct ieee802_1x_mka_participant * participant,const u8 * mka_msg,size_t msg_len)1952 ieee802_1x_mka_decode_dist_cak_body(
1953 	struct ieee802_1x_mka_participant *participant,
1954 	const u8 *mka_msg, size_t msg_len)
1955 {
1956 	struct ieee802_1x_mka_hdr *hdr;
1957 	size_t body_len;
1958 
1959 	hdr = (struct ieee802_1x_mka_hdr *) mka_msg;
1960 	body_len = get_mka_param_body_len(hdr);
1961 	if (body_len < 28) {
1962 		wpa_printf(MSG_ERROR,
1963 			   "KaY: MKA Use CAK Packet Body Length (%zu bytes) should be 28 or more octets",
1964 			   body_len);
1965 		return -1;
1966 	}
1967 
1968 	return 0;
1969 }
1970 
1971 
1972 /**
1973  * ieee802_1x_mka_decode_kmd_body -
1974  */
1975 static int
ieee802_1x_mka_decode_kmd_body(struct ieee802_1x_mka_participant * participant,const u8 * mka_msg,size_t msg_len)1976 ieee802_1x_mka_decode_kmd_body(
1977 	struct ieee802_1x_mka_participant *participant,
1978 	const u8 *mka_msg, size_t msg_len)
1979 {
1980 	struct ieee802_1x_mka_hdr *hdr;
1981 	size_t body_len;
1982 
1983 	hdr = (struct ieee802_1x_mka_hdr *) mka_msg;
1984 	body_len = get_mka_param_body_len(hdr);
1985 	if (body_len < 5) {
1986 		wpa_printf(MSG_ERROR,
1987 			   "KaY: MKA Use KMD Packet Body Length (%zu bytes) should be 5 or more octets",
1988 			   body_len);
1989 		return -1;
1990 	}
1991 
1992 	return 0;
1993 }
1994 
1995 
1996 /**
1997  * ieee802_1x_mka_decode_announce_body -
1998  */
ieee802_1x_mka_decode_announce_body(struct ieee802_1x_mka_participant * participant,const u8 * mka_msg,size_t msg_len)1999 static int ieee802_1x_mka_decode_announce_body(
2000 	struct ieee802_1x_mka_participant *participant,
2001 	const u8 *mka_msg, size_t msg_len)
2002 {
2003 	return 0;
2004 }
2005 
2006 
2007 struct mka_param_body_handler {
2008 	int (*body_tx)(struct ieee802_1x_mka_participant *participant,
2009 		       struct wpabuf *buf);
2010 	int (*body_rx)(struct ieee802_1x_mka_participant *participant,
2011 		       const u8 *mka_msg, size_t msg_len);
2012 	int (*body_length)(struct ieee802_1x_mka_participant *participant);
2013 	bool (*body_present)(struct ieee802_1x_mka_participant *participant);
2014 };
2015 
2016 
2017 static struct mka_param_body_handler mka_body_handler[] = {
2018 	/* Basic parameter set */
2019 	{
2020 		.body_tx      = ieee802_1x_mka_encode_basic_body,
2021 		.body_rx      = NULL,
2022 		.body_length  = ieee802_1x_mka_basic_body_length,
2023 		.body_present = ieee802_1x_mka_basic_body_present
2024 	},
2025 
2026 	/* Live Peer List parameter set */
2027 	{
2028 		.body_tx      = ieee802_1x_mka_encode_live_peer_body,
2029 		.body_rx      = ieee802_1x_mka_decode_live_peer_body,
2030 		.body_length  = ieee802_1x_mka_get_live_peer_length,
2031 		.body_present = ieee802_1x_mka_live_peer_body_present
2032 	},
2033 
2034 	/* Potential Peer List parameter set */
2035 	{
2036 		.body_tx      = ieee802_1x_mka_encode_potential_peer_body,
2037 		.body_rx      = ieee802_1x_mka_decode_potential_peer_body,
2038 		.body_length  = ieee802_1x_mka_get_potential_peer_length,
2039 		.body_present = ieee802_1x_mka_potential_peer_body_present
2040 	},
2041 
2042 	/* MACsec SAK Use parameter set */
2043 	{
2044 		.body_tx      = ieee802_1x_mka_encode_sak_use_body,
2045 		.body_rx      = ieee802_1x_mka_decode_sak_use_body,
2046 		.body_length  = ieee802_1x_mka_get_sak_use_length,
2047 		.body_present = ieee802_1x_mka_sak_use_body_present
2048 	},
2049 
2050 	/* Distributed SAK parameter set */
2051 	{
2052 		.body_tx      = ieee802_1x_mka_encode_dist_sak_body,
2053 		.body_rx      = ieee802_1x_mka_decode_dist_sak_body,
2054 		.body_length  = ieee802_1x_mka_get_dist_sak_length,
2055 		.body_present = ieee802_1x_mka_dist_sak_body_present
2056 	},
2057 
2058 	/* Distribute CAK parameter set */
2059 	{
2060 		.body_tx      = NULL,
2061 		.body_rx      = ieee802_1x_mka_decode_dist_cak_body,
2062 		.body_length  = NULL,
2063 		.body_present = NULL
2064 	},
2065 
2066 	/* KMD parameter set */
2067 	{
2068 		.body_tx      = NULL,
2069 		.body_rx      = ieee802_1x_mka_decode_kmd_body,
2070 		.body_length  = NULL,
2071 		.body_present = NULL
2072 	},
2073 
2074 	/* Announcement parameter set */
2075 	{
2076 		.body_tx      = NULL,
2077 		.body_rx      = ieee802_1x_mka_decode_announce_body,
2078 		.body_length  = NULL,
2079 		.body_present = NULL
2080 	},
2081 
2082 	/* ICV Indicator parameter set */
2083 	{
2084 		.body_tx      = ieee802_1x_mka_encode_icv_body,
2085 		.body_rx      = NULL,
2086 		.body_length  = ieee802_1x_mka_get_icv_length,
2087 		.body_present = ieee802_1x_mka_icv_body_present
2088 	},
2089 };
2090 
2091 
2092 /**
2093  * ieee802_1x_kay_use_data_key - Take reference on a key
2094  */
ieee802_1x_kay_use_data_key(struct data_key * pkey)2095 static void ieee802_1x_kay_use_data_key(struct data_key *pkey)
2096 {
2097 	pkey->user++;
2098 }
2099 
2100 
2101 /**
2102  * ieee802_1x_kay_deinit_data_key - Release reference on a key and
2103  * free if there are no remaining users
2104  */
ieee802_1x_kay_deinit_data_key(struct data_key * pkey)2105 static void ieee802_1x_kay_deinit_data_key(struct data_key *pkey)
2106 {
2107 	if (!pkey)
2108 		return;
2109 
2110 	pkey->user--;
2111 	if (pkey->user > 1)
2112 		return;
2113 
2114 	os_free(pkey->key);
2115 	os_free(pkey);
2116 }
2117 
2118 
2119 /**
2120  * ieee802_1x_kay_generate_new_sak -
2121  */
2122 static int
ieee802_1x_kay_generate_new_sak(struct ieee802_1x_mka_participant * participant)2123 ieee802_1x_kay_generate_new_sak(struct ieee802_1x_mka_participant *participant)
2124 {
2125 	struct data_key *sa_key = NULL;
2126 	struct ieee802_1x_kay_peer *peer;
2127 	struct ieee802_1x_kay *kay = participant->kay;
2128 	int ctx_len, ctx_offset;
2129 	u8 *context;
2130 	unsigned int key_len;
2131 	u8 *key;
2132 	struct macsec_ciphersuite *cs;
2133 
2134 	/* check condition for generating a fresh SAK:
2135 	 * must have one live peer
2136 	 * and MKA life time elapse since last distribution
2137 	 * or potential peer is empty
2138 	 */
2139 	if (dl_list_empty(&participant->live_peers)) {
2140 		wpa_printf(MSG_ERROR,
2141 			   "KaY: Live peers list must not be empty when generating fresh SAK");
2142 		return -1;
2143 	}
2144 
2145 	/* FIXME: A fresh SAK not generated until
2146 	 * the live peer list contains at least one peer and
2147 	 * MKA life time has elapsed since the prior SAK was first distributed,
2148 	 * or the Key server's potential peer is empty
2149 	 * but I can't understand the second item, so
2150 	 * here only check first item and ingore
2151 	 *   && (!dl_list_empty(&participant->potential_peers))) {
2152 	 */
2153 	if ((time(NULL) - kay->dist_time) < MKA_LIFE_TIME / 1000) {
2154 		wpa_printf(MSG_ERROR,
2155 			   "KaY: Life time has not elapsed since prior SAK distributed");
2156 		return -1;
2157 	}
2158 
2159 	cs = &cipher_suite_tbl[kay->macsec_csindex];
2160 	key_len = cs->sak_len;
2161 	key = os_zalloc(key_len);
2162 	if (!key) {
2163 		wpa_printf(MSG_ERROR, "KaY-%s: Out of memory", __func__);
2164 		return -1;
2165 	}
2166 
2167 	ctx_len = key_len + sizeof(kay->dist_kn);
2168 	dl_list_for_each(peer, &participant->live_peers,
2169 			 struct ieee802_1x_kay_peer, list)
2170 		ctx_len += sizeof(peer->mi);
2171 	ctx_len += sizeof(participant->mi);
2172 
2173 	context = os_zalloc(ctx_len);
2174 	if (!context)
2175 		goto fail;
2176 
2177 	ctx_offset = 0;
2178 	if (os_get_random(context + ctx_offset, key_len) < 0)
2179 		goto fail;
2180 
2181 	ctx_offset += key_len;
2182 	dl_list_for_each(peer, &participant->live_peers,
2183 			 struct ieee802_1x_kay_peer, list) {
2184 		os_memcpy(context + ctx_offset, peer->mi, sizeof(peer->mi));
2185 		ctx_offset += sizeof(peer->mi);
2186 	}
2187 	os_memcpy(context + ctx_offset, participant->mi,
2188 		  sizeof(participant->mi));
2189 	ctx_offset += sizeof(participant->mi);
2190 	os_memcpy(context + ctx_offset, &kay->dist_kn, sizeof(kay->dist_kn));
2191 
2192 	if (key_len == 16 || key_len == 32) {
2193 		if (ieee802_1x_sak_aes_cmac(participant->cak.key,
2194 					    participant->cak.len,
2195 					    context, ctx_len,
2196 					    key, key_len)) {
2197 			wpa_printf(MSG_ERROR, "KaY: Failed to generate SAK");
2198 			goto fail;
2199 		}
2200 	} else {
2201 		wpa_printf(MSG_ERROR, "KaY: SAK Length(%u) not supported",
2202 			   key_len);
2203 		goto fail;
2204 	}
2205 	wpa_hexdump_key(MSG_DEBUG, "KaY: generated new SAK", key, key_len);
2206 	os_free(context);
2207 	context = NULL;
2208 
2209 	sa_key = os_zalloc(sizeof(*sa_key));
2210 	if (!sa_key) {
2211 		wpa_printf(MSG_ERROR, "KaY-%s: Out of memory", __func__);
2212 		goto fail;
2213 	}
2214 
2215 	sa_key->key = key;
2216 	sa_key->key_len = key_len;
2217 	os_memcpy(sa_key->key_identifier.mi, participant->mi, MI_LEN);
2218 	sa_key->key_identifier.kn = kay->dist_kn;
2219 
2220 	sa_key->confidentiality_offset = kay->macsec_confidentiality;
2221 	sa_key->an = kay->dist_an;
2222 	ieee802_1x_kay_init_data_key(sa_key);
2223 
2224 	participant->new_key = sa_key;
2225 
2226 	ieee802_1x_kay_use_data_key(sa_key);
2227 	dl_list_add(&participant->sak_list, &sa_key->list);
2228 
2229 	ieee802_1x_cp_set_ciphersuite(kay->cp, cs->id);
2230 	ieee802_1x_cp_sm_step(kay->cp);
2231 	ieee802_1x_cp_set_offset(kay->cp, kay->macsec_confidentiality);
2232 	ieee802_1x_cp_sm_step(kay->cp);
2233 	ieee802_1x_cp_set_distributedki(kay->cp, &sa_key->key_identifier);
2234 	ieee802_1x_cp_set_distributedan(kay->cp, sa_key->an);
2235 	ieee802_1x_cp_signal_newsak(kay->cp);
2236 	ieee802_1x_cp_sm_step(kay->cp);
2237 
2238 	dl_list_for_each(peer, &participant->live_peers,
2239 			 struct ieee802_1x_kay_peer, list)
2240 		peer->sak_used = false;
2241 
2242 	kay->dist_kn++;
2243 	kay->dist_an++;
2244 	if (kay->dist_an > 3)
2245 		kay->dist_an = 0;
2246 
2247 	kay->dist_time = time(NULL);
2248 
2249 	return 0;
2250 
2251 fail:
2252 	os_free(key);
2253 	os_free(context);
2254 	return -1;
2255 }
2256 
2257 
compare_priorities(const struct ieee802_1x_kay_peer * peer,const struct ieee802_1x_kay_peer * other)2258 static int compare_priorities(const struct ieee802_1x_kay_peer *peer,
2259 			      const struct ieee802_1x_kay_peer *other)
2260 {
2261 	if (peer->key_server_priority < other->key_server_priority)
2262 		return -1;
2263 	if (other->key_server_priority < peer->key_server_priority)
2264 		return 1;
2265 
2266 	return os_memcmp(peer->sci.addr, other->sci.addr, ETH_ALEN);
2267 }
2268 
2269 
2270 /**
2271  * ieee802_1x_kay_elect_key_server - elect the key server
2272  * when to elect: whenever the live peers list changes
2273  */
2274 static int
ieee802_1x_kay_elect_key_server(struct ieee802_1x_mka_participant * participant)2275 ieee802_1x_kay_elect_key_server(struct ieee802_1x_mka_participant *participant)
2276 {
2277 	struct ieee802_1x_kay_peer *peer;
2278 	struct ieee802_1x_kay_peer *key_server = NULL;
2279 	struct ieee802_1x_kay *kay = participant->kay;
2280 	bool i_is_key_server;
2281 	int priority_comparison;
2282 
2283 	if (participant->is_obliged_key_server) {
2284 		participant->new_sak = true;
2285 		participant->to_dist_sak = false;
2286 		ieee802_1x_cp_set_electedself(kay->cp, true);
2287 		return 0;
2288 	}
2289 
2290 	/* elect the key server among the peers */
2291 	dl_list_for_each(peer, &participant->live_peers,
2292 			 struct ieee802_1x_kay_peer, list) {
2293 		if (!peer->is_key_server)
2294 			continue;
2295 
2296 		if (!key_server) {
2297 			key_server = peer;
2298 			continue;
2299 		}
2300 
2301 		if (compare_priorities(peer, key_server) < 0)
2302 			key_server = peer;
2303 	}
2304 
2305 	/* elect the key server between me and the above elected peer */
2306 	i_is_key_server = false;
2307 	if (key_server && participant->can_be_key_server) {
2308 		struct ieee802_1x_kay_peer tmp;
2309 
2310 		tmp.key_server_priority = kay->actor_priority;
2311 		os_memcpy(&tmp.sci, &kay->actor_sci, sizeof(tmp.sci));
2312 		priority_comparison = compare_priorities(&tmp, key_server);
2313 		if (priority_comparison < 0) {
2314 			i_is_key_server = true;
2315 		} else if (priority_comparison == 0) {
2316 			wpa_printf(MSG_WARNING,
2317 				   "KaY: Cannot elect key server between me and peer, duplicate MAC detected");
2318 			key_server = NULL;
2319 		}
2320 	} else if (participant->can_be_key_server) {
2321 		i_is_key_server = true;
2322 	}
2323 
2324 	if (i_is_key_server) {
2325 		ieee802_1x_cp_set_electedself(kay->cp, true);
2326 		if (!sci_equal(&kay->key_server_sci, &kay->actor_sci)) {
2327 			ieee802_1x_cp_signal_chgdserver(kay->cp);
2328 			ieee802_1x_cp_sm_step(kay->cp);
2329 		}
2330 
2331 		participant->is_key_server = true;
2332 		participant->principal = true;
2333 		participant->new_sak = true;
2334 		wpa_printf(MSG_DEBUG, "KaY: I am elected as key server");
2335 		participant->to_dist_sak = false;
2336 		participant->is_elected = true;
2337 
2338 		os_memcpy(&kay->key_server_sci, &kay->actor_sci,
2339 			  sizeof(kay->key_server_sci));
2340 		kay->key_server_priority = kay->actor_priority;
2341 	} else if (key_server) {
2342 		wpa_printf(MSG_DEBUG,
2343 			   "KaY: Peer %s was elected as the key server",
2344 			   mi_txt(key_server->mi));
2345 		ieee802_1x_cp_set_electedself(kay->cp, false);
2346 		if (!sci_equal(&kay->key_server_sci, &key_server->sci)) {
2347 			ieee802_1x_cp_signal_chgdserver(kay->cp);
2348 			ieee802_1x_cp_sm_step(kay->cp);
2349 		}
2350 
2351 		participant->is_key_server = false;
2352 		participant->principal = true;
2353 		participant->is_elected = true;
2354 
2355 		os_memcpy(&kay->key_server_sci, &key_server->sci,
2356 			  sizeof(kay->key_server_sci));
2357 		kay->key_server_priority = key_server->key_server_priority;
2358 	} else {
2359 		participant->principal = false;
2360 		participant->is_key_server = false;
2361 		participant->is_elected = false;
2362 	}
2363 
2364 	return 0;
2365 }
2366 
2367 
2368 /**
2369  * ieee802_1x_kay_decide_macsec_use - the key server determinate
2370  *		 how to use MACsec: whether use MACsec and its capability
2371  * protectFrames will be advised if the key server and one of its live peers are
2372  * MACsec capable and one of those request MACsec protection
2373  */
2374 static int
ieee802_1x_kay_decide_macsec_use(struct ieee802_1x_mka_participant * participant)2375 ieee802_1x_kay_decide_macsec_use(
2376 	struct ieee802_1x_mka_participant *participant)
2377 {
2378 	struct ieee802_1x_kay *kay = participant->kay;
2379 	struct ieee802_1x_kay_peer *peer;
2380 	enum macsec_cap less_capability;
2381 	bool has_peer;
2382 
2383 	if (!participant->is_key_server)
2384 		return -1;
2385 
2386 	/* key server self is MACsec-desired and requesting MACsec */
2387 	if (!kay->macsec_desired) {
2388 		participant->advised_desired = false;
2389 		return -1;
2390 	}
2391 	if (kay->macsec_capable == MACSEC_CAP_NOT_IMPLEMENTED) {
2392 		participant->advised_desired = false;
2393 		return -1;
2394 	}
2395 	less_capability = kay->macsec_capable;
2396 
2397 	/* at least one of peers is MACsec-desired and requesting MACsec */
2398 	has_peer = false;
2399 	dl_list_for_each(peer, &participant->live_peers,
2400 			 struct ieee802_1x_kay_peer, list) {
2401 		if (!peer->macsec_desired)
2402 			continue;
2403 
2404 		if (peer->macsec_capability == MACSEC_CAP_NOT_IMPLEMENTED)
2405 			continue;
2406 
2407 		less_capability = (less_capability < peer->macsec_capability) ?
2408 			less_capability : peer->macsec_capability;
2409 		has_peer = true;
2410 	}
2411 
2412 	if (has_peer) {
2413 		participant->advised_desired = true;
2414 		participant->advised_capability = less_capability;
2415 		kay->authenticated = false;
2416 		kay->secured = true;
2417 		kay->failed = false;
2418 		ieee802_1x_cp_connect_secure(kay->cp);
2419 		ieee802_1x_cp_sm_step(kay->cp);
2420 	} else {
2421 		participant->advised_desired = false;
2422 		participant->advised_capability = MACSEC_CAP_NOT_IMPLEMENTED;
2423 		participant->to_use_sak = false;
2424 		kay->authenticated = true;
2425 		kay->secured = false;
2426 		kay->failed = false;
2427 		kay->ltx_kn = 0;
2428 		kay->ltx_an = 0;
2429 		kay->lrx_kn = 0;
2430 		kay->lrx_an = 0;
2431 		kay->otx_kn = 0;
2432 		kay->otx_an = 0;
2433 		kay->orx_kn = 0;
2434 		kay->orx_an = 0;
2435 		ieee802_1x_cp_connect_authenticated(kay->cp);
2436 		ieee802_1x_cp_sm_step(kay->cp);
2437 	}
2438 
2439 	return 0;
2440 }
2441 
2442 static const u8 pae_group_addr[ETH_ALEN] = {
2443 	0x01, 0x80, 0xc2, 0x00, 0x00, 0x03
2444 };
2445 
2446 
2447 /**
2448  * ieee802_1x_kay_encode_mkpdu -
2449  */
2450 static int
ieee802_1x_kay_encode_mkpdu(struct ieee802_1x_mka_participant * participant,struct wpabuf * pbuf)2451 ieee802_1x_kay_encode_mkpdu(struct ieee802_1x_mka_participant *participant,
2452 			    struct wpabuf *pbuf)
2453 {
2454 	unsigned int i;
2455 	struct ieee8023_hdr *ether_hdr;
2456 	struct ieee802_1x_hdr *eapol_hdr;
2457 
2458 	ether_hdr = wpabuf_put(pbuf, sizeof(*ether_hdr));
2459 	os_memcpy(ether_hdr->dest, pae_group_addr, sizeof(ether_hdr->dest));
2460 	os_memcpy(ether_hdr->src, participant->kay->actor_sci.addr,
2461 		  sizeof(ether_hdr->dest));
2462 	ether_hdr->ethertype = host_to_be16(ETH_P_EAPOL);
2463 	wpa_printf(MSG_DEBUG, "KaY: Ethernet header: DA=" MACSTR " SA=" MACSTR
2464 		   " Ethertype=0x%x",
2465 		   MAC2STR(ether_hdr->dest), MAC2STR(ether_hdr->src),
2466 		   be_to_host16(ether_hdr->ethertype));
2467 
2468 	eapol_hdr = wpabuf_put(pbuf, sizeof(*eapol_hdr));
2469 	eapol_hdr->version = EAPOL_VERSION;
2470 	eapol_hdr->type = IEEE802_1X_TYPE_EAPOL_MKA;
2471 	eapol_hdr->length = host_to_be16(wpabuf_tailroom(pbuf));
2472 	wpa_printf(MSG_DEBUG,
2473 		   "KaY: Common EAPOL PDU structure: Protocol Version=%u Packet Type=%u Packet Body Length=%u",
2474 		   eapol_hdr->version, eapol_hdr->type,
2475 		   be_to_host16(eapol_hdr->length));
2476 
2477 	for (i = 0; i < ARRAY_SIZE(mka_body_handler); i++) {
2478 		if (mka_body_handler[i].body_present &&
2479 		    mka_body_handler[i].body_present(participant)) {
2480 			if (mka_body_handler[i].body_tx(participant, pbuf))
2481 				return -1;
2482 		}
2483 	}
2484 
2485 	return 0;
2486 }
2487 
2488 
2489 /**
2490  * ieee802_1x_participant_send_mkpdu -
2491  */
2492 static int
ieee802_1x_participant_send_mkpdu(struct ieee802_1x_mka_participant * participant)2493 ieee802_1x_participant_send_mkpdu(
2494 	struct ieee802_1x_mka_participant *participant)
2495 {
2496 	struct wpabuf *buf;
2497 	struct ieee802_1x_kay *kay = participant->kay;
2498 	size_t length = 0;
2499 	unsigned int i;
2500 
2501 	wpa_printf(MSG_DEBUG, "KaY: Encode and send an MKPDU (ifname=%s)",
2502 		   kay->if_name);
2503 	length += sizeof(struct ieee802_1x_hdr) + sizeof(struct ieee8023_hdr);
2504 	for (i = 0; i < ARRAY_SIZE(mka_body_handler); i++) {
2505 		if (mka_body_handler[i].body_present &&
2506 		    mka_body_handler[i].body_present(participant))
2507 			length += mka_body_handler[i].body_length(participant);
2508 	}
2509 
2510 	buf = wpabuf_alloc(length);
2511 	if (!buf) {
2512 		wpa_printf(MSG_ERROR, "KaY: out of memory");
2513 		return -1;
2514 	}
2515 
2516 	if (ieee802_1x_kay_encode_mkpdu(participant, buf)) {
2517 		wpa_printf(MSG_ERROR, "KaY: encode mkpdu fail");
2518 		return -1;
2519 	}
2520 
2521 	wpa_hexdump_buf(MSG_MSGDUMP, "KaY: Outgoing MKPDU", buf);
2522 	l2_packet_send(kay->l2_mka, NULL, 0, wpabuf_head(buf), wpabuf_len(buf));
2523 	wpabuf_free(buf);
2524 
2525 	kay->active = true;
2526 	participant->active = true;
2527 
2528 	return 0;
2529 }
2530 
2531 
2532 static void ieee802_1x_kay_deinit_transmit_sa(struct transmit_sa *psa);
2533 
ieee802_1x_delete_transmit_sa(struct ieee802_1x_kay * kay,struct transmit_sa * sa)2534 static void ieee802_1x_delete_transmit_sa(struct ieee802_1x_kay *kay,
2535 					  struct transmit_sa *sa)
2536 {
2537 	secy_disable_transmit_sa(kay, sa);
2538 	secy_delete_transmit_sa(kay, sa);
2539 	ieee802_1x_kay_deinit_transmit_sa(sa);
2540 }
2541 
2542 
2543 /**
2544  * ieee802_1x_participant_timer -
2545  */
ieee802_1x_participant_timer(void * eloop_ctx,void * timeout_ctx)2546 static void ieee802_1x_participant_timer(void *eloop_ctx, void *timeout_ctx)
2547 {
2548 	struct ieee802_1x_mka_participant *participant;
2549 	struct ieee802_1x_kay *kay;
2550 	struct ieee802_1x_kay_peer *peer, *pre_peer;
2551 	time_t now = time(NULL);
2552 	bool lp_changed;
2553 	struct receive_sc *rxsc, *pre_rxsc;
2554 	struct transmit_sa *txsa, *pre_txsa;
2555 
2556 	participant = (struct ieee802_1x_mka_participant *)eloop_ctx;
2557 	kay = participant->kay;
2558 	wpa_printf(MSG_DEBUG, "KaY: Participant timer (ifname=%s)",
2559 		   kay->if_name);
2560 	if (participant->cak_life) {
2561 		if (now > participant->cak_life)
2562 			goto delete_mka;
2563 	}
2564 
2565 	/* should delete MKA instance if there are not live peers
2566 	 * when the MKA life elapsed since its creating */
2567 	if (participant->mka_life) {
2568 		if (dl_list_empty(&participant->live_peers)) {
2569 			if (now > participant->mka_life)
2570 				goto delete_mka;
2571 		} else {
2572 			participant->mka_life = 0;
2573 		}
2574 	}
2575 
2576 	lp_changed = false;
2577 	dl_list_for_each_safe(peer, pre_peer, &participant->live_peers,
2578 			      struct ieee802_1x_kay_peer, list) {
2579 		if (now > peer->expire) {
2580 			wpa_printf(MSG_DEBUG, "KaY: Live peer removed");
2581 			wpa_hexdump(MSG_DEBUG, "\tMI: ", peer->mi,
2582 				    sizeof(peer->mi));
2583 			wpa_printf(MSG_DEBUG, "\tMN: %d", peer->mn);
2584 			dl_list_for_each_safe(rxsc, pre_rxsc,
2585 					      &participant->rxsc_list,
2586 					      struct receive_sc, list) {
2587 				if (sci_equal(&rxsc->sci, &peer->sci)) {
2588 					ieee802_1x_kay_deinit_receive_sc(
2589 						participant, rxsc);
2590 				}
2591 			}
2592 			dl_list_del(&peer->list);
2593 			os_free(peer);
2594 			lp_changed = true;
2595 		}
2596 	}
2597 
2598 	if (lp_changed) {
2599 		if (dl_list_empty(&participant->live_peers)) {
2600 			participant->advised_desired = false;
2601 			participant->advised_capability =
2602 				MACSEC_CAP_NOT_IMPLEMENTED;
2603 			participant->to_use_sak = false;
2604 			participant->ltx = false;
2605 			participant->lrx = false;
2606 			participant->otx = false;
2607 			participant->orx = false;
2608 			participant->is_key_server = false;
2609 			participant->is_elected = false;
2610 			kay->authenticated = false;
2611 			kay->secured = false;
2612 			kay->failed = false;
2613 			kay->ltx_kn = 0;
2614 			kay->ltx_an = 0;
2615 			kay->lrx_kn = 0;
2616 			kay->lrx_an = 0;
2617 			kay->otx_kn = 0;
2618 			kay->otx_an = 0;
2619 			kay->orx_kn = 0;
2620 			kay->orx_an = 0;
2621 			dl_list_for_each_safe(txsa, pre_txsa,
2622 					      &participant->txsc->sa_list,
2623 					      struct transmit_sa, list) {
2624 				ieee802_1x_delete_transmit_sa(kay, txsa);
2625 			}
2626 
2627 			ieee802_1x_cp_connect_pending(kay->cp);
2628 			ieee802_1x_cp_sm_step(kay->cp);
2629 		} else {
2630 			ieee802_1x_kay_elect_key_server(participant);
2631 			ieee802_1x_kay_decide_macsec_use(participant);
2632 		}
2633 	}
2634 
2635 	dl_list_for_each_safe(peer, pre_peer, &participant->potential_peers,
2636 			      struct ieee802_1x_kay_peer, list) {
2637 		if (now > peer->expire) {
2638 			wpa_printf(MSG_DEBUG, "KaY: Potential peer removed");
2639 			wpa_hexdump(MSG_DEBUG, "\tMI: ", peer->mi,
2640 				    sizeof(peer->mi));
2641 			wpa_printf(MSG_DEBUG, "\tMN: %d", peer->mn);
2642 			dl_list_del(&peer->list);
2643 			os_free(peer);
2644 		}
2645 	}
2646 
2647 	if (participant->new_sak && participant->is_key_server) {
2648 		if (!ieee802_1x_kay_generate_new_sak(participant))
2649 			participant->to_dist_sak = true;
2650 
2651 		participant->new_sak = false;
2652 	}
2653 
2654 	if (participant->retry_count < MAX_RETRY_CNT ||
2655 	    participant->mode == PSK) {
2656 		ieee802_1x_participant_send_mkpdu(participant);
2657 		participant->retry_count++;
2658 	}
2659 
2660 	eloop_register_timeout(kay->mka_hello_time / 1000, 0,
2661 			       ieee802_1x_participant_timer,
2662 			       participant, NULL);
2663 
2664 	return;
2665 
2666 delete_mka:
2667 	kay->authenticated = false;
2668 	kay->secured = false;
2669 	kay->failed = true;
2670 	ieee802_1x_kay_delete_mka(kay, &participant->ckn);
2671 }
2672 
2673 
2674 /**
2675  * ieee802_1x_kay_init_transmit_sa -
2676  */
2677 static struct transmit_sa *
ieee802_1x_kay_init_transmit_sa(struct transmit_sc * psc,u8 an,u32 next_PN,struct data_key * key)2678 ieee802_1x_kay_init_transmit_sa(struct transmit_sc *psc, u8 an, u32 next_PN,
2679 				struct data_key *key)
2680 {
2681 	struct transmit_sa *psa;
2682 
2683 	key->tx_latest = true;
2684 	key->rx_latest = true;
2685 
2686 	psa = os_zalloc(sizeof(*psa));
2687 	if (!psa) {
2688 		wpa_printf(MSG_ERROR, "%s: out of memory", __func__);
2689 		return NULL;
2690 	}
2691 
2692 	if (key->confidentiality_offset >= CONFIDENTIALITY_OFFSET_0 &&
2693 	    key->confidentiality_offset <= CONFIDENTIALITY_OFFSET_50)
2694 		psa->confidentiality = true;
2695 	else
2696 		psa->confidentiality = false;
2697 
2698 	psa->an = an;
2699 	ieee802_1x_kay_use_data_key(key);
2700 	psa->pkey = key;
2701 	psa->next_pn = next_PN;
2702 	psa->sc = psc;
2703 
2704 	os_get_time(&psa->created_time);
2705 	psa->in_use = false;
2706 
2707 	dl_list_add(&psc->sa_list, &psa->list);
2708 	wpa_printf(MSG_DEBUG,
2709 		   "KaY: Create transmit SA(an: %hhu, next_pn: %u) of SC",
2710 		   an, next_PN);
2711 
2712 	return psa;
2713 }
2714 
2715 
2716 /**
2717  * ieee802_1x_kay_deinit_transmit_sa -
2718  */
ieee802_1x_kay_deinit_transmit_sa(struct transmit_sa * psa)2719 static void ieee802_1x_kay_deinit_transmit_sa(struct transmit_sa *psa)
2720 {
2721 	ieee802_1x_kay_deinit_data_key(psa->pkey);
2722 	psa->pkey = NULL;
2723 	wpa_printf(MSG_DEBUG,
2724 		   "KaY: Delete transmit SA(an: %hhu) of SC",
2725 		   psa->an);
2726 	dl_list_del(&psa->list);
2727 	os_free(psa);
2728 }
2729 
2730 
2731 /**
2732  * init_transmit_sc -
2733  */
2734 static struct transmit_sc *
ieee802_1x_kay_init_transmit_sc(const struct ieee802_1x_mka_sci * sci)2735 ieee802_1x_kay_init_transmit_sc(const struct ieee802_1x_mka_sci *sci)
2736 {
2737 	struct transmit_sc *psc;
2738 
2739 	psc = os_zalloc(sizeof(*psc));
2740 	if (!psc) {
2741 		wpa_printf(MSG_ERROR, "%s: out of memory", __func__);
2742 		return NULL;
2743 	}
2744 	os_memcpy(&psc->sci, sci, sizeof(psc->sci));
2745 
2746 	os_get_time(&psc->created_time);
2747 	psc->transmitting = false;
2748 	psc->encoding_sa = false;
2749 	psc->enciphering_sa = false;
2750 
2751 	dl_list_init(&psc->sa_list);
2752 	wpa_printf(MSG_DEBUG, "KaY: Create transmit SC - SCI: %s",
2753 		   sci_txt(&psc->sci));
2754 
2755 	return psc;
2756 }
2757 
2758 
2759 /**
2760  * ieee802_1x_kay_deinit_transmit_sc -
2761  */
2762 static void
ieee802_1x_kay_deinit_transmit_sc(struct ieee802_1x_mka_participant * participant,struct transmit_sc * psc)2763 ieee802_1x_kay_deinit_transmit_sc(
2764 	struct ieee802_1x_mka_participant *participant, struct transmit_sc *psc)
2765 {
2766 	struct transmit_sa *psa, *tmp;
2767 
2768 	wpa_printf(MSG_DEBUG, "KaY: Delete transmit SC");
2769 	dl_list_for_each_safe(psa, tmp, &psc->sa_list, struct transmit_sa, list)
2770 		ieee802_1x_delete_transmit_sa(participant->kay, psa);
2771 
2772 	secy_delete_transmit_sc(participant->kay, psc);
2773 	os_free(psc);
2774 }
2775 
2776 
2777 /****************** Interface between CP and KAY *********************/
2778 /**
2779  * ieee802_1x_kay_set_latest_sa_attr -
2780  */
ieee802_1x_kay_set_latest_sa_attr(struct ieee802_1x_kay * kay,struct ieee802_1x_mka_ki * lki,u8 lan,bool ltx,bool lrx)2781 int ieee802_1x_kay_set_latest_sa_attr(struct ieee802_1x_kay *kay,
2782 				      struct ieee802_1x_mka_ki *lki, u8 lan,
2783 				      bool ltx, bool lrx)
2784 {
2785 	struct ieee802_1x_mka_participant *principal;
2786 
2787 	principal = ieee802_1x_kay_get_principal_participant(kay);
2788 	if (!principal)
2789 		return -1;
2790 
2791 	if (!lki)
2792 		os_memset(&principal->lki, 0, sizeof(principal->lki));
2793 	else
2794 		os_memcpy(&principal->lki, lki, sizeof(principal->lki));
2795 
2796 	principal->lan = lan;
2797 	principal->ltx = ltx;
2798 	principal->lrx = lrx;
2799 	if (!lki) {
2800 		kay->ltx_kn = 0;
2801 		kay->lrx_kn = 0;
2802 	} else {
2803 		kay->ltx_kn = lki->kn;
2804 		kay->lrx_kn = lki->kn;
2805 	}
2806 	kay->ltx_an = lan;
2807 	kay->lrx_an = lan;
2808 
2809 	return 0;
2810 }
2811 
2812 
2813 /**
2814  * ieee802_1x_kay_set_old_sa_attr -
2815  */
ieee802_1x_kay_set_old_sa_attr(struct ieee802_1x_kay * kay,struct ieee802_1x_mka_ki * oki,u8 oan,bool otx,bool orx)2816 int ieee802_1x_kay_set_old_sa_attr(struct ieee802_1x_kay *kay,
2817 				   struct ieee802_1x_mka_ki *oki,
2818 				   u8 oan, bool otx, bool orx)
2819 {
2820 	struct ieee802_1x_mka_participant *principal;
2821 
2822 	principal = ieee802_1x_kay_get_principal_participant(kay);
2823 	if (!principal)
2824 		return -1;
2825 
2826 	if (!oki)
2827 		os_memset(&principal->oki, 0, sizeof(principal->oki));
2828 	else
2829 		os_memcpy(&principal->oki, oki, sizeof(principal->oki));
2830 
2831 	principal->oan = oan;
2832 	principal->otx = otx;
2833 	principal->orx = orx;
2834 
2835 	if (!oki) {
2836 		kay->otx_kn = 0;
2837 		kay->orx_kn = 0;
2838 	} else {
2839 		kay->otx_kn = oki->kn;
2840 		kay->orx_kn = oki->kn;
2841 	}
2842 	kay->otx_an = oan;
2843 	kay->orx_an = oan;
2844 
2845 	return 0;
2846 }
2847 
2848 
lookup_txsa_by_an(struct transmit_sc * txsc,u8 an)2849 static struct transmit_sa * lookup_txsa_by_an(struct transmit_sc *txsc, u8 an)
2850 {
2851 	struct transmit_sa *txsa;
2852 
2853 	dl_list_for_each(txsa, &txsc->sa_list, struct transmit_sa, list) {
2854 		if (txsa->an == an)
2855 			return txsa;
2856 	}
2857 
2858 	return NULL;
2859 }
2860 
2861 
lookup_rxsa_by_an(struct receive_sc * rxsc,u8 an)2862 static struct receive_sa * lookup_rxsa_by_an(struct receive_sc *rxsc, u8 an)
2863 {
2864 	struct receive_sa *rxsa;
2865 
2866 	dl_list_for_each(rxsa, &rxsc->sa_list, struct receive_sa, list) {
2867 		if (rxsa->an == an)
2868 			return rxsa;
2869 	}
2870 
2871 	return NULL;
2872 }
2873 
2874 
2875 /**
2876  * ieee802_1x_kay_create_sas -
2877  */
ieee802_1x_kay_create_sas(struct ieee802_1x_kay * kay,struct ieee802_1x_mka_ki * lki)2878 int ieee802_1x_kay_create_sas(struct ieee802_1x_kay *kay,
2879 			      struct ieee802_1x_mka_ki *lki)
2880 {
2881 	struct data_key *sa_key, *latest_sak;
2882 	struct ieee802_1x_mka_participant *principal;
2883 	struct receive_sc *rxsc;
2884 	struct receive_sa *rxsa;
2885 	struct transmit_sa *txsa;
2886 
2887 	principal = ieee802_1x_kay_get_principal_participant(kay);
2888 	if (!principal)
2889 		return -1;
2890 
2891 	latest_sak = NULL;
2892 	dl_list_for_each(sa_key, &principal->sak_list, struct data_key, list) {
2893 		if (is_ki_equal(&sa_key->key_identifier, lki)) {
2894 			sa_key->rx_latest = true;
2895 			sa_key->tx_latest = true;
2896 			latest_sak = sa_key;
2897 			principal->to_use_sak = true;
2898 		} else {
2899 			sa_key->rx_latest = false;
2900 			sa_key->tx_latest = false;
2901 		}
2902 	}
2903 	if (!latest_sak) {
2904 		wpa_printf(MSG_ERROR, "KaY: lki related sak not found");
2905 		return -1;
2906 	}
2907 
2908 	dl_list_for_each(rxsc, &principal->rxsc_list, struct receive_sc, list) {
2909 		while ((rxsa = lookup_rxsa_by_an(rxsc, latest_sak->an)) != NULL)
2910 			ieee802_1x_delete_receive_sa(kay, rxsa);
2911 
2912 		rxsa = ieee802_1x_kay_init_receive_sa(rxsc, latest_sak->an, 1,
2913 						      latest_sak);
2914 		if (!rxsa)
2915 			return -1;
2916 
2917 		secy_create_receive_sa(kay, rxsa);
2918 	}
2919 
2920 	while ((txsa = lookup_txsa_by_an(principal->txsc, latest_sak->an)) !=
2921 	       NULL)
2922 		ieee802_1x_delete_transmit_sa(kay, txsa);
2923 
2924 	txsa = ieee802_1x_kay_init_transmit_sa(principal->txsc, latest_sak->an,
2925 					       latest_sak->next_pn ?
2926 					       latest_sak->next_pn : 1,
2927 					       latest_sak);
2928 	if (!txsa)
2929 		return -1;
2930 
2931 	secy_create_transmit_sa(kay, txsa);
2932 
2933 
2934 
2935 	return 0;
2936 }
2937 
2938 
2939 /**
2940  * ieee802_1x_kay_delete_sas -
2941  */
ieee802_1x_kay_delete_sas(struct ieee802_1x_kay * kay,struct ieee802_1x_mka_ki * ki)2942 int ieee802_1x_kay_delete_sas(struct ieee802_1x_kay *kay,
2943 			      struct ieee802_1x_mka_ki *ki)
2944 {
2945 	struct data_key *sa_key, *pre_key;
2946 	struct transmit_sa *txsa, *pre_txsa;
2947 	struct receive_sa *rxsa, *pre_rxsa;
2948 	struct receive_sc *rxsc;
2949 	struct ieee802_1x_mka_participant *principal;
2950 
2951 	wpa_printf(MSG_DEBUG, "KaY: Entry into %s", __func__);
2952 	principal = ieee802_1x_kay_get_principal_participant(kay);
2953 	if (!principal)
2954 		return -1;
2955 
2956 	/* remove the transmit sa */
2957 	dl_list_for_each_safe(txsa, pre_txsa, &principal->txsc->sa_list,
2958 			      struct transmit_sa, list) {
2959 		if (is_ki_equal(&txsa->pkey->key_identifier, ki))
2960 			ieee802_1x_delete_transmit_sa(kay, txsa);
2961 	}
2962 
2963 	/* remove the receive sa */
2964 	dl_list_for_each(rxsc, &principal->rxsc_list, struct receive_sc, list) {
2965 		dl_list_for_each_safe(rxsa, pre_rxsa, &rxsc->sa_list,
2966 				      struct receive_sa, list) {
2967 			if (is_ki_equal(&rxsa->pkey->key_identifier, ki))
2968 				ieee802_1x_delete_receive_sa(kay, rxsa);
2969 		}
2970 	}
2971 
2972 	/* remove the sak */
2973 	dl_list_for_each_safe(sa_key, pre_key, &principal->sak_list,
2974 			      struct data_key, list) {
2975 		if (is_ki_equal(&sa_key->key_identifier, ki)) {
2976 			if (principal->new_key == sa_key)
2977 				principal->new_key = NULL;
2978 			dl_list_del(&sa_key->list);
2979 			ieee802_1x_kay_deinit_data_key(sa_key);
2980 			break;
2981 		}
2982 	}
2983 
2984 	return 0;
2985 }
2986 
2987 
2988 /**
2989  * ieee802_1x_kay_enable_tx_sas -
2990  */
ieee802_1x_kay_enable_tx_sas(struct ieee802_1x_kay * kay,struct ieee802_1x_mka_ki * lki)2991 int ieee802_1x_kay_enable_tx_sas(struct ieee802_1x_kay *kay,
2992 				 struct ieee802_1x_mka_ki *lki)
2993 {
2994 	struct ieee802_1x_mka_participant *principal;
2995 	struct transmit_sa *txsa;
2996 
2997 	principal = ieee802_1x_kay_get_principal_participant(kay);
2998 	if (!principal)
2999 		return -1;
3000 
3001 	dl_list_for_each(txsa, &principal->txsc->sa_list, struct transmit_sa,
3002 			 list) {
3003 		if (is_ki_equal(&txsa->pkey->key_identifier, lki)) {
3004 			txsa->in_use = true;
3005 			secy_enable_transmit_sa(kay, txsa);
3006 			ieee802_1x_cp_set_usingtransmitas(
3007 				principal->kay->cp, true);
3008 			ieee802_1x_cp_sm_step(principal->kay->cp);
3009 		}
3010 	}
3011 
3012 	return 0;
3013 }
3014 
3015 
3016 /**
3017  * ieee802_1x_kay_enable_rx_sas -
3018  */
ieee802_1x_kay_enable_rx_sas(struct ieee802_1x_kay * kay,struct ieee802_1x_mka_ki * lki)3019 int ieee802_1x_kay_enable_rx_sas(struct ieee802_1x_kay *kay,
3020 				 struct ieee802_1x_mka_ki *lki)
3021 {
3022 	struct ieee802_1x_mka_participant *principal;
3023 	struct receive_sa *rxsa;
3024 	struct receive_sc *rxsc;
3025 
3026 	principal = ieee802_1x_kay_get_principal_participant(kay);
3027 	if (!principal)
3028 		return -1;
3029 
3030 	dl_list_for_each(rxsc, &principal->rxsc_list, struct receive_sc, list) {
3031 		dl_list_for_each(rxsa, &rxsc->sa_list, struct receive_sa, list)
3032 		{
3033 			if (is_ki_equal(&rxsa->pkey->key_identifier, lki)) {
3034 				rxsa->in_use = true;
3035 				secy_enable_receive_sa(kay, rxsa);
3036 				ieee802_1x_cp_set_usingreceivesas(
3037 					principal->kay->cp, true);
3038 				ieee802_1x_cp_sm_step(principal->kay->cp);
3039 			}
3040 		}
3041 	}
3042 
3043 	return 0;
3044 }
3045 
3046 
3047 /**
3048  * ieee802_1x_kay_enable_new_info -
3049  */
ieee802_1x_kay_enable_new_info(struct ieee802_1x_kay * kay)3050 int ieee802_1x_kay_enable_new_info(struct ieee802_1x_kay *kay)
3051 {
3052 	struct ieee802_1x_mka_participant *principal;
3053 
3054 	principal = ieee802_1x_kay_get_principal_participant(kay);
3055 	if (!principal)
3056 		return -1;
3057 
3058 	if (principal->retry_count < MAX_RETRY_CNT || principal->mode == PSK) {
3059 		ieee802_1x_participant_send_mkpdu(principal);
3060 		principal->retry_count++;
3061 	}
3062 
3063 	return 0;
3064 }
3065 
3066 
3067 /**
3068  * ieee802_1x_kay_mkpdu_validity_check -
3069  * Validity checks specified in IEEE Std 802.1X-2010, 11.11.2 (Validation of
3070  * MKPDUs)
3071  */
ieee802_1x_kay_mkpdu_validity_check(struct ieee802_1x_kay * kay,const u8 * buf,size_t len)3072 static int ieee802_1x_kay_mkpdu_validity_check(struct ieee802_1x_kay *kay,
3073 					       const u8 *buf, size_t len)
3074 {
3075 	struct ieee8023_hdr *eth_hdr;
3076 	struct ieee802_1x_hdr *eapol_hdr;
3077 	struct ieee802_1x_mka_hdr *mka_hdr;
3078 	struct ieee802_1x_mka_basic_body *body;
3079 	size_t mka_msg_len;
3080 	struct ieee802_1x_mka_participant *participant;
3081 	size_t body_len;
3082 	size_t ckn_len;
3083 	u8 icv[MAX_ICV_LEN];
3084 	const u8 *msg_icv;
3085 
3086 	/* len > eth+eapol header already verified in kay_l2_receive();
3087 	 * likewise, eapol_hdr->length validated there */
3088 	eth_hdr = (struct ieee8023_hdr *) buf;
3089 	eapol_hdr = (struct ieee802_1x_hdr *) (eth_hdr + 1);
3090 	mka_hdr = (struct ieee802_1x_mka_hdr *) (eapol_hdr + 1);
3091 
3092 	wpa_printf(MSG_DEBUG, "KaY: Ethernet header: DA=" MACSTR " SA=" MACSTR
3093 		   " Ethertype=0x%x",
3094 		   MAC2STR(eth_hdr->dest), MAC2STR(eth_hdr->src),
3095 		   be_to_host16(eth_hdr->ethertype));
3096 
3097 	/* the destination address shall not be an individual address */
3098 	if (os_memcmp(eth_hdr->dest, pae_group_addr, ETH_ALEN) != 0) {
3099 		wpa_printf(MSG_DEBUG,
3100 			   "KaY: ethernet destination address is not PAE group address");
3101 		return -1;
3102 	}
3103 
3104 	wpa_printf(MSG_DEBUG,
3105 		   "KaY: Common EAPOL PDU structure: Protocol Version=%u Packet Type=%u Packet Body Length=%u",
3106 		   eapol_hdr->version, eapol_hdr->type,
3107 		   be_to_host16(eapol_hdr->length));
3108 
3109 	/* MKPDU shall not be less than 32 octets */
3110 	mka_msg_len = be_to_host16(eapol_hdr->length);
3111 	if (mka_msg_len < 32) {
3112 		wpa_printf(MSG_DEBUG, "KaY: MKPDU is less than 32 octets");
3113 		return -1;
3114 	}
3115 	/* MKPDU shall be a multiple of 4 octets */
3116 	if ((mka_msg_len % 4) != 0) {
3117 		wpa_printf(MSG_DEBUG,
3118 			   "KaY: MKPDU is not multiple of 4 octets");
3119 		return -1;
3120 	}
3121 
3122 	wpa_hexdump(MSG_MSGDUMP, "KaY: EAPOL-MKA Packet Body (MKPDU)",
3123 		    mka_hdr, mka_msg_len);
3124 
3125 	/* Room for body_len already verified in kay_l2_receive() */
3126 	body = (struct ieee802_1x_mka_basic_body *) mka_hdr;
3127 	body_len = get_mka_param_body_len(body);
3128 	/* EAPOL-MKA body should comprise basic parameter set and ICV */
3129 	if (mka_msg_len < MKA_HDR_LEN + body_len + DEFAULT_ICV_LEN) {
3130 		wpa_printf(MSG_ERROR,
3131 			   "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",
3132 			   mka_msg_len, MKA_HDR_LEN,
3133 			   body_len, DEFAULT_ICV_LEN);
3134 		return -1;
3135 	}
3136 
3137 	if (body_len < sizeof(struct ieee802_1x_mka_basic_body) - MKA_HDR_LEN) {
3138 		wpa_printf(MSG_DEBUG, "KaY: Too small body length %zu",
3139 			   body_len);
3140 		return -1;
3141 	}
3142 	ckn_len = body_len -
3143 		(sizeof(struct ieee802_1x_mka_basic_body) - MKA_HDR_LEN);
3144 	if (ckn_len < 1 || ckn_len > MAX_CKN_LEN) {
3145 		wpa_printf(MSG_WARNING,
3146 			   "KaY: Received EAPOL-MKA CKN Length (%zu bytes) is out of range (<= %u bytes)",
3147 			   ckn_len, MAX_CKN_LEN);
3148 		return -1;
3149 	}
3150 
3151 	ieee802_1x_mka_dump_basic_body(body);
3152 
3153 	/* CKN should be owned by I */
3154 	participant = ieee802_1x_kay_get_participant(kay, body->ckn, ckn_len);
3155 	if (!participant) {
3156 		wpa_printf(MSG_DEBUG, "KaY: CKN is not included in my CA");
3157 		return -1;
3158 	}
3159 
3160 	/* algorithm agility check */
3161 	if (os_memcmp(body->algo_agility, mka_algo_agility,
3162 		      sizeof(body->algo_agility)) != 0) {
3163 		wpa_printf(MSG_INFO,
3164 			   "KaY: Peer's algorithm agility (%s) not supported",
3165 			   algo_agility_txt(body->algo_agility));
3166 		return -1;
3167 	}
3168 
3169 	/* ICV check */
3170 	/*
3171 	 * The ICV will comprise the final octets of the packet body, whatever
3172 	 * its size, not the fixed length 16 octets, indicated by the EAPOL
3173 	 * packet body length.
3174 	 */
3175 	if (len < mka_alg_tbl[kay->mka_algindex].icv_len ||
3176 	    mka_alg_tbl[kay->mka_algindex].icv_hash(
3177 		    participant->ick.key, participant->ick.len,
3178 		    buf, len - mka_alg_tbl[kay->mka_algindex].icv_len, icv)) {
3179 		wpa_printf(MSG_ERROR, "KaY: Failed to calculate ICV");
3180 		return -1;
3181 	}
3182 
3183 	msg_icv = ieee802_1x_mka_decode_icv_body(participant,
3184 						 (const u8 *) mka_hdr,
3185 						 mka_msg_len);
3186 	if (!msg_icv) {
3187 		wpa_printf(MSG_WARNING, "KaY: No ICV in MKPDU - ignore it");
3188 		return -1;
3189 	}
3190 	wpa_hexdump(MSG_DEBUG, "KaY: Received ICV",
3191 		    msg_icv, mka_alg_tbl[kay->mka_algindex].icv_len);
3192 	if (os_memcmp_const(msg_icv, icv,
3193 			    mka_alg_tbl[kay->mka_algindex].icv_len) != 0) {
3194 		wpa_printf(MSG_WARNING,
3195 			   "KaY: Computed ICV is not equal to Received ICV");
3196 		wpa_hexdump(MSG_DEBUG, "KaY: Calculated ICV",
3197 			    icv, mka_alg_tbl[kay->mka_algindex].icv_len);
3198 		return -1;
3199 	}
3200 
3201 	return 0;
3202 }
3203 
3204 
3205 /**
3206  * ieee802_1x_kay_decode_mkpdu -
3207  */
ieee802_1x_kay_decode_mkpdu(struct ieee802_1x_kay * kay,const u8 * buf,size_t len)3208 static int ieee802_1x_kay_decode_mkpdu(struct ieee802_1x_kay *kay,
3209 				       const u8 *buf, size_t len)
3210 {
3211 	struct ieee802_1x_mka_participant *participant;
3212 	struct ieee802_1x_mka_hdr *hdr;
3213 	struct ieee802_1x_kay_peer *peer;
3214 	size_t body_len;
3215 	size_t left_len;
3216 	u8 body_type;
3217 	int i;
3218 	const u8 *pos;
3219 	bool handled[256];
3220 	bool bad_sak_use = false; /* Error detected while processing SAK Use
3221 				   * parameter set */
3222 	bool i_in_peerlist, is_in_live_peer, is_in_potential_peer;
3223 
3224 	wpa_printf(MSG_DEBUG, "KaY: Decode received MKPDU (ifname=%s)",
3225 		   kay->if_name);
3226 	if (ieee802_1x_kay_mkpdu_validity_check(kay, buf, len))
3227 		return -1;
3228 
3229 	/* handle basic parameter set */
3230 	pos = buf + sizeof(struct ieee8023_hdr) + sizeof(struct ieee802_1x_hdr);
3231 	left_len = len - sizeof(struct ieee8023_hdr) -
3232 		sizeof(struct ieee802_1x_hdr);
3233 	participant = ieee802_1x_mka_decode_basic_body(kay, pos, left_len);
3234 	if (!participant)
3235 		return -1;
3236 
3237 	/* to skip basic parameter set */
3238 	hdr = (struct ieee802_1x_mka_hdr *) pos;
3239 	body_len = MKA_ALIGN_LENGTH(get_mka_param_body_len(hdr));
3240 	if (left_len < body_len + MKA_HDR_LEN)
3241 		return -1;
3242 	pos += body_len + MKA_HDR_LEN;
3243 	left_len -= body_len + MKA_HDR_LEN;
3244 
3245 	/* check i am in the peer's peer list */
3246 	i_in_peerlist = ieee802_1x_mka_i_in_peerlist(participant, pos,
3247 						     left_len);
3248 	is_in_live_peer = ieee802_1x_kay_is_in_live_peer(
3249 		participant, participant->current_peer_id.mi);
3250 	wpa_printf(MSG_DEBUG, "KaY: i_in_peerlist=%s is_in_live_peer=%s",
3251 		   yes_no(i_in_peerlist), yes_no(is_in_live_peer));
3252 	if (i_in_peerlist && !is_in_live_peer) {
3253 		/* accept the peer as live peer */
3254 		is_in_potential_peer = ieee802_1x_kay_is_in_potential_peer(
3255 			participant, participant->current_peer_id.mi);
3256 		if (is_in_potential_peer) {
3257 			if (!ieee802_1x_kay_move_live_peer(
3258 				    participant,
3259 				    participant->current_peer_id.mi,
3260 				    be_to_host32(participant->
3261 						 current_peer_id.mn)))
3262 				return -1;
3263 		} else if (!ieee802_1x_kay_create_live_peer(
3264 				   participant, participant->current_peer_id.mi,
3265 				   be_to_host32(participant->
3266 						current_peer_id.mn))) {
3267 				return -1;
3268 		}
3269 
3270 		ieee802_1x_kay_elect_key_server(participant);
3271 		ieee802_1x_kay_decide_macsec_use(participant);
3272 	}
3273 
3274 	/*
3275 	 * Handle other parameter set than basic parameter set.
3276 	 * Each parameter set should be present only once.
3277 	 */
3278 	for (i = 0; i < 256; i++)
3279 		handled[i] = false;
3280 
3281 	handled[0] = true;
3282 	for (; left_len > MKA_HDR_LEN + DEFAULT_ICV_LEN;
3283 	     pos += body_len + MKA_HDR_LEN,
3284 		     left_len -= body_len + MKA_HDR_LEN) {
3285 		hdr = (struct ieee802_1x_mka_hdr *) pos;
3286 		body_len = MKA_ALIGN_LENGTH(get_mka_param_body_len(hdr));
3287 		body_type = get_mka_param_body_type(hdr);
3288 
3289 		if (body_type == MKA_ICV_INDICATOR)
3290 			return 0;
3291 
3292 		if (left_len < (MKA_HDR_LEN + body_len + DEFAULT_ICV_LEN)) {
3293 			wpa_printf(MSG_ERROR,
3294 				   "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",
3295 				   left_len, MKA_HDR_LEN,
3296 				   body_len, DEFAULT_ICV_LEN);
3297 			return -1;
3298 		}
3299 
3300 		if (handled[body_type]) {
3301 			wpa_printf(MSG_DEBUG,
3302 				   "KaY: Ignore duplicated body type %u",
3303 				   body_type);
3304 			continue;
3305 		}
3306 
3307 		handled[body_type] = true;
3308 		if (body_type < ARRAY_SIZE(mka_body_handler) &&
3309 		    mka_body_handler[body_type].body_rx) {
3310 			if (mka_body_handler[body_type].body_rx
3311 				(participant, pos, left_len) != 0) {
3312 				/* Handle parameter set failure */
3313 				if (body_type != MKA_SAK_USE) {
3314 					wpa_printf(MSG_INFO,
3315 						   "KaY: Discarding Rx MKPDU: decode of parameter set type (%d) failed",
3316 						   body_type);
3317 					return -1;
3318 				}
3319 
3320 				/* Ideally DIST-SAK should be processed before
3321 				 * SAK-USE. Unfortunately IEEE Std 802.1X-2010,
3322 				 * 11.11.3 (Encoding MKPDUs) states SAK-USE(3)
3323 				 * must always be encoded before DIST-SAK(4).
3324 				 * Rather than redesigning mka_body_handler so
3325 				 * that it somehow processes DIST-SAK before
3326 				 * SAK-USE, just ignore SAK-USE failures if
3327 				 * DIST-SAK is also present in this MKPDU. */
3328 				bad_sak_use = true;
3329 			}
3330 		} else {
3331 			wpa_printf(MSG_ERROR,
3332 				   "KaY: The body type %d is not supported in this MKA version %d",
3333 				   body_type, MKA_VERSION_ID);
3334 		}
3335 	}
3336 
3337 	if (bad_sak_use && !handled[MKA_DISTRIBUTED_SAK]) {
3338 		wpa_printf(MSG_INFO,
3339 			   "KaY: Discarding Rx MKPDU: decode of parameter set type (%d) failed",
3340 			   MKA_SAK_USE);
3341 		if (!reset_participant_mi(participant))
3342 			wpa_printf(MSG_DEBUG, "KaY: Could not update mi");
3343 		else
3344 			wpa_printf(MSG_DEBUG,
3345 				   "KaY: Selected a new random MI: %s",
3346 				   mi_txt(participant->mi));
3347 		return -1;
3348 	}
3349 
3350 	/* Detect missing parameter sets */
3351 	peer = ieee802_1x_kay_get_live_peer(participant,
3352 					    participant->current_peer_id.mi);
3353 	if (peer) {
3354 		/* MKPDU is from live peer */
3355 		if (!handled[MKA_SAK_USE]) {
3356 			/* Once a live peer starts sending SAK-USE, it should be
3357 			 * sent every time. */
3358 			if (peer->sak_used) {
3359 				wpa_printf(MSG_INFO,
3360 					   "KaY: Discarding Rx MKPDU: Live Peer stopped sending SAK-USE");
3361 				return -1;
3362 			}
3363 
3364 			/* Live peer is probably hung if it hasn't sent SAK-USE
3365 			 * after a reasonable number of MKPDUs. Drop the MKPDU,
3366 			 * which will eventually force an timeout. */
3367 			if (++peer->missing_sak_use_count >
3368 			    MAX_MISSING_SAK_USE) {
3369 				wpa_printf(MSG_INFO,
3370 					   "KaY: Discarding Rx MKPDU: Live Peer not sending SAK-USE");
3371 				return -1;
3372 			}
3373 		} else {
3374 			peer->missing_sak_use_count = 0;
3375 
3376 			/* Only update live peer watchdog after successful
3377 			 * decode of all parameter sets */
3378 			peer->expire = time(NULL) + MKA_LIFE_TIME / 1000;
3379 		}
3380 	} else {
3381 		/* MKPDU is from new or potential peer */
3382 		peer = ieee802_1x_kay_get_peer(participant,
3383 					       participant->current_peer_id.mi);
3384 		if (!peer) {
3385 			wpa_printf(MSG_DEBUG, "KaY: No peer entry found");
3386 			return -1;
3387 		}
3388 
3389 		/* Do not update potential peer watchdog. Per IEEE Std
3390 		 * 802.1X-2010, 9.4.3, potential peers need to show liveness by
3391 		 * including our MI/MN in their transmitted MKPDU (within
3392 		 * potential or live parameter sets). Whena potential peer does
3393 		 * include our MI/MN in an MKPDU, we respond by moving the peer
3394 		 * from 'potential_peers' to 'live_peers'. */
3395 	}
3396 
3397 	kay->active = true;
3398 	participant->retry_count = 0;
3399 	participant->active = true;
3400 
3401 	return 0;
3402 }
3403 
3404 
3405 
kay_l2_receive(void * ctx,const u8 * src_addr,const u8 * buf,size_t len)3406 static void kay_l2_receive(void *ctx, const u8 *src_addr, const u8 *buf,
3407 			   size_t len)
3408 {
3409 	struct ieee802_1x_kay *kay = ctx;
3410 	struct ieee8023_hdr *eth_hdr;
3411 	struct ieee802_1x_hdr *eapol_hdr;
3412 	size_t calc_len;
3413 
3414 	/* IEEE Std 802.1X-2010, 11.4 (Validation of received EAPOL PDUs) */
3415 
3416 	/* must contain at least ieee8023_hdr + ieee802_1x_hdr */
3417 	if (len < sizeof(*eth_hdr) + sizeof(*eapol_hdr)) {
3418 		wpa_printf(MSG_MSGDUMP, "KaY: EAPOL frame too short (%lu)",
3419 			   (unsigned long) len);
3420 		return;
3421 	}
3422 
3423 	eth_hdr = (struct ieee8023_hdr *) buf;
3424 	eapol_hdr = (struct ieee802_1x_hdr *) (eth_hdr + 1);
3425 	calc_len = sizeof(*eth_hdr) + sizeof(*eapol_hdr) +
3426 		be_to_host16(eapol_hdr->length);
3427 	if (len < calc_len) {
3428 		wpa_printf(MSG_MSGDUMP, "KaY: EAPOL MPDU is invalid: (received len %lu, calculated len %lu, EAPOL length %u)",
3429 			   (unsigned long) len,
3430 			   (unsigned long) calc_len,
3431 			   be_to_host16(eapol_hdr->length));
3432 		return;
3433 	}
3434 	if (len > calc_len) {
3435 		wpa_hexdump(MSG_DEBUG,
3436 			    "KaY: Ignore extra octets following the Packey Body field",
3437 			    &buf[calc_len], len - calc_len);
3438 		len = calc_len;
3439 	}
3440 
3441 	if (eapol_hdr->version < EAPOL_VERSION) {
3442 		wpa_printf(MSG_MSGDUMP, "KaY: version %d does not support MKA",
3443 			   eapol_hdr->version);
3444 		return;
3445 	}
3446 	if (be_to_host16(eth_hdr->ethertype) != ETH_P_PAE ||
3447 	    eapol_hdr->type != IEEE802_1X_TYPE_EAPOL_MKA)
3448 		return; /* ignore other EAPOL types silently here */
3449 
3450 	wpa_hexdump(MSG_DEBUG, "KaY: RX EAPOL-MKA", buf, len);
3451 	if (dl_list_empty(&kay->participant_list)) {
3452 		wpa_printf(MSG_ERROR,
3453 			   "KaY: No MKA participant instance - ignore EAPOL-MKA");
3454 		return;
3455 	}
3456 
3457 	ieee802_1x_kay_decode_mkpdu(kay, buf, len);
3458 }
3459 
3460 
3461 /**
3462  * ieee802_1x_kay_init -
3463  */
3464 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,u16 port,u8 priority,u32 macsec_csindex,const char * ifname,const u8 * addr)3465 ieee802_1x_kay_init(struct ieee802_1x_kay_ctx *ctx, enum macsec_policy policy,
3466 		    bool macsec_replay_protect, u32 macsec_replay_window,
3467 		    u16 port, u8 priority, u32 macsec_csindex,
3468 		    const char *ifname, const u8 *addr)
3469 {
3470 	struct ieee802_1x_kay *kay;
3471 
3472 	wpa_printf(MSG_DEBUG, "KaY: Initialize - ifname=%s addr=" MACSTR
3473 		   " port=%u priority=%u",
3474 		   ifname, MAC2STR(addr), port, priority);
3475 	kay = os_zalloc(sizeof(*kay));
3476 	if (!kay) {
3477 		wpa_printf(MSG_ERROR, "KaY-%s: out of memory", __func__);
3478 		os_free(ctx);
3479 		return NULL;
3480 	}
3481 
3482 	kay->ctx = ctx;
3483 
3484 	kay->enable = true;
3485 	kay->active = false;
3486 
3487 	kay->authenticated = false;
3488 	kay->secured = false;
3489 	kay->failed = false;
3490 	kay->policy = policy;
3491 
3492 	os_strlcpy(kay->if_name, ifname, IFNAMSIZ);
3493 	os_memcpy(kay->actor_sci.addr, addr, ETH_ALEN);
3494 	kay->actor_sci.port = host_to_be16(port ? port : 0x0001);
3495 	wpa_printf(MSG_DEBUG, "KaY: Generated SCI: %s",
3496 		   sci_txt(&kay->actor_sci));
3497 	kay->actor_priority = priority;
3498 
3499 	/* While actor acts as a key server, shall distribute sakey */
3500 	kay->dist_kn = 1;
3501 	kay->dist_an = 0;
3502 	kay->dist_time = 0;
3503 
3504 	kay->pn_exhaustion = PENDING_PN_EXHAUSTION;
3505 	kay->macsec_csindex = macsec_csindex;
3506 	kay->mka_algindex = DEFAULT_MKA_ALG_INDEX;
3507 	kay->mka_version = MKA_VERSION_ID;
3508 
3509 	os_memcpy(kay->algo_agility, mka_algo_agility,
3510 		  sizeof(kay->algo_agility));
3511 
3512 	dl_list_init(&kay->participant_list);
3513 
3514 	if (policy != DO_NOT_SECURE &&
3515 	    secy_get_capability(kay, &kay->macsec_capable) < 0)
3516 		goto error;
3517 
3518 	if (policy == DO_NOT_SECURE ||
3519 	    kay->macsec_capable == MACSEC_CAP_NOT_IMPLEMENTED) {
3520 		kay->macsec_capable = MACSEC_CAP_NOT_IMPLEMENTED;
3521 		kay->macsec_desired = false;
3522 		kay->macsec_protect = false;
3523 		kay->macsec_encrypt = false;
3524 		kay->macsec_validate = Disabled;
3525 		kay->macsec_replay_protect = false;
3526 		kay->macsec_replay_window = 0;
3527 		kay->macsec_confidentiality = CONFIDENTIALITY_NONE;
3528 		kay->mka_hello_time = MKA_HELLO_TIME;
3529 	} else {
3530 		kay->macsec_desired = true;
3531 		kay->macsec_protect = true;
3532 		if (kay->macsec_capable >= MACSEC_CAP_INTEG_AND_CONF &&
3533 		    policy == SHOULD_ENCRYPT) {
3534 			kay->macsec_encrypt = true;
3535 			kay->macsec_confidentiality = CONFIDENTIALITY_OFFSET_0;
3536 		} else { /* SHOULD_SECURE */
3537 			kay->macsec_encrypt = false;
3538 			kay->macsec_confidentiality = CONFIDENTIALITY_NONE;
3539 		}
3540 		kay->macsec_validate = Strict;
3541 		kay->macsec_replay_protect = macsec_replay_protect;
3542 		kay->macsec_replay_window = macsec_replay_window;
3543 		kay->mka_hello_time = MKA_HELLO_TIME;
3544 	}
3545 
3546 	wpa_printf(MSG_DEBUG, "KaY: state machine created");
3547 
3548 	/* Initialize the SecY must be prio to CP, as CP will control SecY */
3549 	if (secy_init_macsec(kay) < 0) {
3550 		wpa_printf(MSG_DEBUG, "KaY: Could not initialize MACsec");
3551 		goto error;
3552 	}
3553 
3554 	wpa_printf(MSG_DEBUG, "KaY: secy init macsec done");
3555 
3556 	/* init CP */
3557 	kay->cp = ieee802_1x_cp_sm_init(kay);
3558 	if (kay->cp == NULL)
3559 		goto error;
3560 
3561 	if (policy == DO_NOT_SECURE) {
3562 		ieee802_1x_cp_connect_authenticated(kay->cp);
3563 		ieee802_1x_cp_sm_step(kay->cp);
3564 	} else {
3565 		kay->l2_mka = l2_packet_init(kay->if_name, NULL, ETH_P_PAE,
3566 					     kay_l2_receive, kay, 1);
3567 		if (kay->l2_mka == NULL) {
3568 			wpa_printf(MSG_WARNING,
3569 				   "KaY: Failed to initialize L2 packet processing for MKA packet");
3570 			goto error;
3571 		}
3572 	}
3573 
3574 	return kay;
3575 
3576 error:
3577 	ieee802_1x_kay_deinit(kay);
3578 	return NULL;
3579 }
3580 
3581 
3582 /**
3583  * ieee802_1x_kay_deinit -
3584  */
3585 void
ieee802_1x_kay_deinit(struct ieee802_1x_kay * kay)3586 ieee802_1x_kay_deinit(struct ieee802_1x_kay *kay)
3587 {
3588 	struct ieee802_1x_mka_participant *participant;
3589 
3590 	if (!kay)
3591 		return;
3592 
3593 	wpa_printf(MSG_DEBUG, "KaY: state machine removed");
3594 
3595 	while (!dl_list_empty(&kay->participant_list)) {
3596 		participant = dl_list_entry(kay->participant_list.next,
3597 					    struct ieee802_1x_mka_participant,
3598 					    list);
3599 		ieee802_1x_kay_delete_mka(kay, &participant->ckn);
3600 	}
3601 
3602 	ieee802_1x_cp_sm_deinit(kay->cp);
3603 	secy_deinit_macsec(kay);
3604 
3605 	if (kay->l2_mka) {
3606 		l2_packet_deinit(kay->l2_mka);
3607 		kay->l2_mka = NULL;
3608 	}
3609 
3610 	os_free(kay->ctx);
3611 	os_free(kay);
3612 }
3613 
3614 
mode_txt(enum mka_created_mode mode)3615 static const char * mode_txt(enum mka_created_mode mode)
3616 {
3617 	switch (mode) {
3618 	case PSK:
3619 		return "PSK";
3620 	case EAP_EXCHANGE:
3621 		return "EAP";
3622 	}
3623 
3624 	return "?";
3625 }
3626 
3627 
3628 /**
3629  * ieee802_1x_kay_create_mka -
3630  */
3631 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)3632 ieee802_1x_kay_create_mka(struct ieee802_1x_kay *kay,
3633 			  const struct mka_key_name *ckn,
3634 			  const struct mka_key *cak, u32 life,
3635 			  enum mka_created_mode mode, bool is_authenticator)
3636 {
3637 	struct ieee802_1x_mka_participant *participant;
3638 	unsigned int usecs;
3639 
3640 	wpa_printf(MSG_DEBUG,
3641 		   "KaY: Create MKA (ifname=%s mode=%s authenticator=%s)",
3642 		   kay->if_name, mode_txt(mode), yes_no(is_authenticator));
3643 
3644 	if (!kay || !ckn || !cak) {
3645 		wpa_printf(MSG_ERROR, "KaY: ckn or cak is null");
3646 		return NULL;
3647 	}
3648 
3649 	if (cak->len != 16 && cak->len != 32) {
3650 		wpa_printf(MSG_ERROR, "KaY: Unexpected CAK length %u",
3651 			   (unsigned int) cak->len);
3652 		return NULL;
3653 	}
3654 	if (ckn->len > MAX_CKN_LEN) {
3655 		wpa_printf(MSG_ERROR, "KaY: CKN is out of range (>32 bytes)");
3656 		return NULL;
3657 	}
3658 	if (!kay->enable) {
3659 		wpa_printf(MSG_ERROR, "KaY: Now is at disable state");
3660 		return NULL;
3661 	}
3662 
3663 	participant = os_zalloc(sizeof(*participant));
3664 	if (!participant) {
3665 		wpa_printf(MSG_ERROR, "KaY-%s: out of memory", __func__);
3666 		return NULL;
3667 	}
3668 
3669 	participant->ckn.len = ckn->len;
3670 	os_memcpy(participant->ckn.name, ckn->name, ckn->len);
3671 	wpa_hexdump(MSG_DEBUG, "KaY: CKN", participant->ckn.name,
3672 		    participant->ckn.len);
3673 	participant->cak.len = cak->len;
3674 	os_memcpy(participant->cak.key, cak->key, cak->len);
3675 	wpa_hexdump_key(MSG_DEBUG, "KaY: CAK", participant->cak.key,
3676 			participant->cak.len);
3677 	if (life)
3678 		participant->cak_life = life + time(NULL);
3679 
3680 	switch (mode) {
3681 	case EAP_EXCHANGE:
3682 		if (is_authenticator) {
3683 			participant->is_obliged_key_server = true;
3684 			participant->can_be_key_server = true;
3685 			participant->is_key_server = true;
3686 			participant->principal = true;
3687 
3688 			os_memcpy(&kay->key_server_sci, &kay->actor_sci,
3689 				  sizeof(kay->key_server_sci));
3690 			kay->key_server_priority = kay->actor_priority;
3691 			participant->is_elected = true;
3692 		} else {
3693 			participant->is_obliged_key_server = false;
3694 			participant->can_be_key_server = false;
3695 			participant->is_key_server = false;
3696 			participant->is_elected = true;
3697 		}
3698 		break;
3699 
3700 	default:
3701 		participant->is_obliged_key_server = false;
3702 		participant->can_be_key_server = true;
3703 		participant->is_key_server = true;
3704 		participant->is_elected = false;
3705 		break;
3706 	}
3707 
3708 	participant->cached = false;
3709 
3710 	participant->active = false;
3711 	participant->participant = false;
3712 	participant->retain = false;
3713 	participant->activate = DEFAULT;
3714 
3715 	if (participant->is_key_server)
3716 		participant->principal = true;
3717 
3718 	dl_list_init(&participant->live_peers);
3719 	dl_list_init(&participant->potential_peers);
3720 
3721 	participant->retry_count = 0;
3722 	participant->kay = kay;
3723 
3724 	if (!reset_participant_mi(participant))
3725 		goto fail;
3726 	wpa_printf(MSG_DEBUG, "KaY: Selected random MI: %s",
3727 		   mi_txt(participant->mi));
3728 
3729 	participant->lrx = false;
3730 	participant->ltx = false;
3731 	participant->orx = false;
3732 	participant->otx = false;
3733 	participant->to_dist_sak = false;
3734 	participant->to_use_sak = false;
3735 	participant->new_sak = false;
3736 	dl_list_init(&participant->sak_list);
3737 	participant->new_key = NULL;
3738 	dl_list_init(&participant->rxsc_list);
3739 	participant->txsc = ieee802_1x_kay_init_transmit_sc(&kay->actor_sci);
3740 	secy_cp_control_protect_frames(kay, kay->macsec_protect);
3741 	secy_cp_control_replay(kay, kay->macsec_replay_protect,
3742 			       kay->macsec_replay_window);
3743 	if (secy_create_transmit_sc(kay, participant->txsc))
3744 		goto fail;
3745 
3746 	/* to derive KEK from CAK and CKN */
3747 	participant->kek.len = participant->cak.len;
3748 	if (mka_alg_tbl[kay->mka_algindex].kek_trfm(participant->cak.key,
3749 						    participant->cak.len,
3750 						    participant->ckn.name,
3751 						    participant->ckn.len,
3752 						    participant->kek.key,
3753 						    participant->kek.len)) {
3754 		wpa_printf(MSG_ERROR, "KaY: KEK derivation failed");
3755 		goto fail;
3756 	}
3757 	wpa_hexdump_key(MSG_DEBUG, "KaY: Derived KEK",
3758 			participant->kek.key, participant->kek.len);
3759 
3760 	/* to derive ICK from CAK and CKN */
3761 	participant->ick.len = participant->cak.len;
3762 	if (mka_alg_tbl[kay->mka_algindex].ick_trfm(participant->cak.key,
3763 						    participant->cak.len,
3764 						    participant->ckn.name,
3765 						    participant->ckn.len,
3766 						    participant->ick.key,
3767 						    participant->ick.len)) {
3768 		wpa_printf(MSG_ERROR, "KaY: ICK derivation failed");
3769 		goto fail;
3770 	}
3771 	wpa_hexdump_key(MSG_DEBUG, "KaY: Derived ICK",
3772 			participant->ick.key, participant->ick.len);
3773 
3774 	dl_list_add(&kay->participant_list, &participant->list);
3775 
3776 	usecs = os_random() % (kay->mka_hello_time * 1000);
3777 	eloop_register_timeout(0, usecs, ieee802_1x_participant_timer,
3778 			       participant, NULL);
3779 
3780 	/* Disable MKA lifetime for PSK mode.
3781 	 * The peer(s) can take a long time to come up, because we
3782 	 * create a "standby" MKA, and we need it to remain live until
3783 	 * some peer appears.
3784 	 */
3785 	if (mode != PSK) {
3786 		participant->mka_life = MKA_LIFE_TIME / 1000 + time(NULL) +
3787 			usecs / 1000000;
3788 	}
3789 	participant->mode = mode;
3790 
3791 	return participant;
3792 
3793 fail:
3794 	os_free(participant->txsc);
3795 	os_free(participant);
3796 	return NULL;
3797 }
3798 
3799 
3800 /**
3801  * ieee802_1x_kay_delete_mka -
3802  */
3803 void
ieee802_1x_kay_delete_mka(struct ieee802_1x_kay * kay,struct mka_key_name * ckn)3804 ieee802_1x_kay_delete_mka(struct ieee802_1x_kay *kay, struct mka_key_name *ckn)
3805 {
3806 	struct ieee802_1x_mka_participant *participant;
3807 	struct ieee802_1x_kay_peer *peer;
3808 	struct data_key *sak;
3809 	struct receive_sc *rxsc;
3810 
3811 	if (!kay || !ckn)
3812 		return;
3813 
3814 	wpa_printf(MSG_DEBUG, "KaY: participant removed");
3815 
3816 	/* get the participant */
3817 	participant = ieee802_1x_kay_get_participant(kay, ckn->name, ckn->len);
3818 	if (!participant) {
3819 		wpa_hexdump(MSG_DEBUG, "KaY: participant is not found",
3820 			    ckn->name, ckn->len);
3821 		return;
3822 	}
3823 
3824 	eloop_cancel_timeout(ieee802_1x_participant_timer, participant, NULL);
3825 	dl_list_del(&participant->list);
3826 
3827 	/* remove live peer */
3828 	while (!dl_list_empty(&participant->live_peers)) {
3829 		peer = dl_list_entry(participant->live_peers.next,
3830 				     struct ieee802_1x_kay_peer, list);
3831 		dl_list_del(&peer->list);
3832 		os_free(peer);
3833 	}
3834 
3835 	/* remove potential peer */
3836 	while (!dl_list_empty(&participant->potential_peers)) {
3837 		peer = dl_list_entry(participant->potential_peers.next,
3838 				     struct ieee802_1x_kay_peer, list);
3839 		dl_list_del(&peer->list);
3840 		os_free(peer);
3841 	}
3842 
3843 	/* remove sak */
3844 	while (!dl_list_empty(&participant->sak_list)) {
3845 		sak = dl_list_entry(participant->sak_list.next,
3846 				    struct data_key, list);
3847 		dl_list_del(&sak->list);
3848 		ieee802_1x_kay_deinit_data_key(sak);
3849 	}
3850 	while (!dl_list_empty(&participant->rxsc_list)) {
3851 		rxsc = dl_list_entry(participant->rxsc_list.next,
3852 				     struct receive_sc, list);
3853 		ieee802_1x_kay_deinit_receive_sc(participant, rxsc);
3854 	}
3855 	ieee802_1x_kay_deinit_transmit_sc(participant, participant->txsc);
3856 
3857 	os_memset(&participant->cak, 0, sizeof(participant->cak));
3858 	os_memset(&participant->kek, 0, sizeof(participant->kek));
3859 	os_memset(&participant->ick, 0, sizeof(participant->ick));
3860 	os_free(participant);
3861 }
3862 
3863 
3864 /**
3865  * ieee802_1x_kay_mka_participate -
3866  */
ieee802_1x_kay_mka_participate(struct ieee802_1x_kay * kay,struct mka_key_name * ckn,bool status)3867 void ieee802_1x_kay_mka_participate(struct ieee802_1x_kay *kay,
3868 				    struct mka_key_name *ckn, bool status)
3869 {
3870 	struct ieee802_1x_mka_participant *participant;
3871 
3872 	if (!kay || !ckn)
3873 		return;
3874 
3875 	participant = ieee802_1x_kay_get_participant(kay, ckn->name, ckn->len);
3876 	if (!participant)
3877 		return;
3878 
3879 	participant->active = status;
3880 }
3881 
3882 
3883 /**
3884  * ieee802_1x_kay_new_sak -
3885  */
3886 int
ieee802_1x_kay_new_sak(struct ieee802_1x_kay * kay)3887 ieee802_1x_kay_new_sak(struct ieee802_1x_kay *kay)
3888 {
3889 	struct ieee802_1x_mka_participant *participant;
3890 
3891 	if (!kay)
3892 		return -1;
3893 
3894 	participant = ieee802_1x_kay_get_principal_participant(kay);
3895 	if (!participant)
3896 		return -1;
3897 
3898 	participant->new_sak = true;
3899 	wpa_printf(MSG_DEBUG, "KaY: new SAK signal");
3900 
3901 	return 0;
3902 }
3903 
3904 
3905 /**
3906  * ieee802_1x_kay_change_cipher_suite -
3907  */
3908 int
ieee802_1x_kay_change_cipher_suite(struct ieee802_1x_kay * kay,unsigned int cs_index)3909 ieee802_1x_kay_change_cipher_suite(struct ieee802_1x_kay *kay,
3910 				   unsigned int cs_index)
3911 {
3912 	struct ieee802_1x_mka_participant *participant;
3913 	enum macsec_cap secy_cap;
3914 
3915 	if (!kay)
3916 		return -1;
3917 
3918 	if (cs_index >= CS_TABLE_SIZE) {
3919 		wpa_printf(MSG_ERROR,
3920 			   "KaY: Configured cipher suite index is out of range");
3921 		return -1;
3922 	}
3923 	if (kay->macsec_csindex == cs_index)
3924 		return -2;
3925 
3926 	if (cs_index == 0)
3927 		kay->macsec_desired = false;
3928 
3929 	kay->macsec_csindex = cs_index;
3930 	kay->macsec_capable = cipher_suite_tbl[kay->macsec_csindex].capable;
3931 
3932 	if (secy_get_capability(kay, &secy_cap) < 0)
3933 		return -3;
3934 
3935 	if (kay->macsec_capable > secy_cap)
3936 		kay->macsec_capable = secy_cap;
3937 
3938 	participant = ieee802_1x_kay_get_principal_participant(kay);
3939 	if (participant) {
3940 		wpa_printf(MSG_INFO, "KaY: Cipher Suite changed");
3941 		participant->new_sak = true;
3942 	}
3943 
3944 	return 0;
3945 }
3946 
3947 
3948 #ifdef CONFIG_CTRL_IFACE
3949 
3950 /**
3951  * ieee802_1x_kay_get_status - Get IEEE 802.1X KaY status details
3952  * @sm: Pointer to KaY allocated with ieee802_1x_kay_init()
3953  * @buf: Buffer for status information
3954  * @buflen: Maximum buffer length
3955  * @verbose: Whether to include verbose status information
3956  * Returns: Number of bytes written to buf.
3957  *
3958  * Query KaY status information. This function fills in a text area with current
3959  * status information. If the buffer (buf) is not large enough, status
3960  * information will be truncated to fit the buffer.
3961  */
ieee802_1x_kay_get_status(struct ieee802_1x_kay * kay,char * buf,size_t buflen)3962 int ieee802_1x_kay_get_status(struct ieee802_1x_kay *kay, char *buf,
3963 			      size_t buflen)
3964 {
3965 	char *pos, *end;
3966 	int res, count;
3967 	struct ieee802_1x_mka_participant *p;
3968 
3969 	if (!kay)
3970 		return 0;
3971 
3972 	pos = buf;
3973 	end = buf + buflen;
3974 
3975 	res = os_snprintf(pos, end - pos,
3976 			  "PAE KaY status=%s\n"
3977 			  "Authenticated=%s\n"
3978 			  "Secured=%s\n"
3979 			  "Failed=%s\n"
3980 			  "Actor Priority=%u\n"
3981 			  "Key Server Priority=%u\n"
3982 			  "Is Key Server=%s\n"
3983 			  "Number of Keys Distributed=%u\n"
3984 			  "Number of Keys Received=%u\n"
3985 			  "MKA Hello Time=%u\n",
3986 			  kay->active ? "Active" : "Not-Active",
3987 			  kay->authenticated ? "Yes" : "No",
3988 			  kay->secured ? "Yes" : "No",
3989 			  kay->failed ? "Yes" : "No",
3990 			  kay->actor_priority,
3991 			  kay->key_server_priority,
3992 			  kay->is_key_server ? "Yes" : "No",
3993 			  kay->dist_kn - 1,
3994 			  kay->rcvd_keys,
3995 			  kay->mka_hello_time);
3996 	if (os_snprintf_error(buflen, res))
3997 		return 0;
3998 	pos += res;
3999 
4000 	res = os_snprintf(pos, end - pos,
4001 			  "actor_sci=%s\n", sci_txt(&kay->actor_sci));
4002 	if (os_snprintf_error(buflen, res))
4003 		return end - pos;
4004 	pos += res;
4005 
4006 	res = os_snprintf(pos, end - pos,
4007 			  "key_server_sci=%s\n", sci_txt(&kay->key_server_sci));
4008 	if (os_snprintf_error(buflen, res))
4009 		return end - pos;
4010 	pos += res;
4011 
4012 	count = 0;
4013 	dl_list_for_each(p, &kay->participant_list,
4014 			 struct ieee802_1x_mka_participant, list) {
4015 		char *pos2 = pos;
4016 
4017 		res = os_snprintf(pos2, end - pos2, "participant_idx=%d\nckn=",
4018 			count);
4019 		if (os_snprintf_error(buflen, res))
4020 			return end - pos;
4021 		pos2 += res;
4022 		count++;
4023 
4024 		pos2 += wpa_snprintf_hex(pos2, end - pos2, p->ckn.name,
4025 					 p->ckn.len);
4026 
4027 		res = os_snprintf(pos2, end - pos2,
4028 				  "\nmi=%s\n"
4029 				  "mn=%u\n"
4030 				  "active=%s\n"
4031 				  "participant=%s\n"
4032 				  "retain=%s\n"
4033 				  "live_peers=%u\n"
4034 				  "potential_peers=%u\n"
4035 				  "is_key_server=%s\n"
4036 				  "is_elected=%s\n",
4037 				  mi_txt(p->mi), p->mn,
4038 				  yes_no(p->active),
4039 				  yes_no(p->participant),
4040 				  yes_no(p->retain),
4041 				  dl_list_len(&p->live_peers),
4042 				  dl_list_len(&p->potential_peers),
4043 				  yes_no(p->is_key_server),
4044 				  yes_no(p->is_elected));
4045 		if (os_snprintf_error(buflen, res))
4046 			return end - pos;
4047 		pos2 += res;
4048 		pos = pos2;
4049 	}
4050 
4051 	return pos - buf;
4052 }
4053 
4054 
true_false(bool val)4055 static const char * true_false(bool val)
4056 {
4057 	return val ? "true" : "false";
4058 }
4059 
4060 
activate_control_txt(enum activate_ctrl activate)4061 static const char * activate_control_txt(enum activate_ctrl activate)
4062 {
4063 	switch (activate) {
4064 	case DEFAULT:
4065 		return "default";
4066 	case DISABLED:
4067 		return "disabled";
4068 	case ON_OPER_UP:
4069 		return "onOperUp";
4070 	case ALWAYS:
4071 		return "always";
4072 	}
4073 
4074 	return "?";
4075 }
4076 
4077 
mka_mib_peer(struct dl_list * peers,bool live,char * buf,char * end)4078 static char * mka_mib_peer(struct dl_list *peers, bool live, char *buf,
4079 			   char *end)
4080 {
4081 	char *pos = buf;
4082 	struct ieee802_1x_kay_peer *p;
4083 	int res;
4084 
4085 	dl_list_for_each(p, peers, struct ieee802_1x_kay_peer, list) {
4086 		res = os_snprintf(pos, end - pos,
4087 				  "ieee8021XKayMkaPeerListMI=%s\n"
4088 				  "ieee8021XKayMkaPeerListMN=%u\n"
4089 				  "ieee8021XKayMkaPeerListType=%u\n"
4090 				  "ieee8021XKayMkaPeerListSCI=%s\n",
4091 				  mi_txt(p->mi),
4092 				  p->mn,
4093 				  live ? 1 : 2,
4094 				  sci_txt(&p->sci));
4095 		if (os_snprintf_error(end - pos, res))
4096 			return pos;
4097 		pos += res;
4098 	}
4099 
4100 	return pos;
4101 }
4102 
4103 
ieee802_1x_kay_get_mib(struct ieee802_1x_kay * kay,char * buf,size_t buflen)4104 int ieee802_1x_kay_get_mib(struct ieee802_1x_kay *kay, char *buf,
4105 			   size_t buflen)
4106 {
4107 	char *pos, *end;
4108 	int res;
4109 	struct ieee802_1x_mka_participant *p;
4110 
4111 	if (!kay)
4112 		return 0;
4113 
4114 	pos = buf;
4115 	end = buf + buflen;
4116 
4117 	dl_list_for_each(p, &kay->participant_list,
4118 			 struct ieee802_1x_mka_participant, list) {
4119 		char *pos2 = pos;
4120 
4121 		res = os_snprintf(pos2, end - pos2, "ieee8021XKayMkaPartCKN=");
4122 		if (os_snprintf_error(buflen, res))
4123 			return end - pos;
4124 		pos2 += res;
4125 
4126 		pos2 += wpa_snprintf_hex(pos2, end - pos2, p->ckn.name,
4127 					 p->ckn.len);
4128 
4129 		res = os_snprintf(pos2, end - pos2,
4130 				  "\nieee8021XKayMkaPartCached=%s\n"
4131 				  "ieee8021XKayMkaPartActive=%s\n"
4132 				  "ieee8021XKayMkaPartRetain=%s\n"
4133 				  "ieee8021XKayMkaPartActivateControl=%s\n"
4134 				  "ieee8021XKayMkaPartPrincipal=%s\n",
4135 				  true_false(p->cached),
4136 				  true_false(p->active),
4137 				  true_false(p->retain),
4138 				  activate_control_txt(p->activate),
4139 				  true_false(p->principal));
4140 		if (os_snprintf_error(buflen, res))
4141 			return end - pos;
4142 		pos2 += res;
4143 		pos = pos2;
4144 
4145 		pos = mka_mib_peer(&p->live_peers, true, pos, end);
4146 		pos = mka_mib_peer(&p->potential_peers, false, pos, end);
4147 	}
4148 
4149 	return pos - buf;
4150 }
4151 
4152 #endif /* CONFIG_CTRL_IFACE */
4153