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