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