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