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