2 * IEEE 802.1X-2010 Key Agree Protocol of PAE state machine
3 * Copyright (c) 2013, Qualcomm Atheros, Inc.
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
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"
26 #define DEFAULT_SA_KEY_LEN 16
27 #define DEFAULT_ICV_LEN 16
28 #define MAX_ICV_LEN 32 /* 32 bytes, 256 bits */
30 #define PENDING_PN_EXHAUSTION 0xC0000000
32 /* IEEE Std 802.1X-2010, Table 9-1 - MKA Algorithm Agility */
33 #define MKA_ALGO_AGILITY_2009 { 0x00, 0x80, 0xC2, 0x01 }
34 static u8 mka_algo_agility
[4] = MKA_ALGO_AGILITY_2009
;
36 /* IEEE802.1AE-2006 Table 14-1 MACsec Cipher Suites */
37 static struct macsec_ciphersuite cipher_suite_tbl
[] = {
42 MACSEC_CAP_INTEG_AND_CONF_0_30_50
,
48 #define CS_TABLE_SIZE (ARRAY_SIZE(cipher_suite_tbl))
49 #define DEFAULT_CS_INDEX 0
51 static struct mka_alg mka_alg_tbl
[] = {
53 MKA_ALGO_AGILITY_2009
,
54 /* 128-bit CAK, KEK, ICK, ICV */
56 ieee802_1x_cak_128bits_aes_cmac
,
57 ieee802_1x_ckn_128bits_aes_cmac
,
58 ieee802_1x_kek_128bits_aes_cmac
,
59 ieee802_1x_ick_128bits_aes_cmac
,
60 ieee802_1x_icv_128bits_aes_cmac
,
65 #define MKA_ALG_TABLE_SIZE (ARRAY_SIZE(mka_alg_tbl))
68 static int is_ki_equal(struct ieee802_1x_mka_ki
*ki1
,
69 struct ieee802_1x_mka_ki
*ki2
)
71 return os_memcmp(ki1
->mi
, ki2
->mi
, MI_LEN
) == 0 &&
76 struct mka_param_body_handler
{
77 int (*body_tx
)(struct ieee802_1x_mka_participant
*participant
,
79 int (*body_rx
)(struct ieee802_1x_mka_participant
*participant
,
80 const u8
*mka_msg
, size_t msg_len
);
81 int (*body_length
)(struct ieee802_1x_mka_participant
*participant
);
82 Boolean (*body_present
)(struct ieee802_1x_mka_participant
*participant
);
86 static void set_mka_param_body_len(void *body
, unsigned int len
)
88 struct ieee802_1x_mka_hdr
*hdr
= body
;
89 hdr
->length
= (len
>> 8) & 0x0f;
90 hdr
->length1
= len
& 0xff;
94 static unsigned int get_mka_param_body_len(const void *body
)
96 const struct ieee802_1x_mka_hdr
*hdr
= body
;
97 return (hdr
->length
<< 8) | hdr
->length1
;
101 static u8
get_mka_param_body_type(const void *body
)
103 const struct ieee802_1x_mka_hdr
*hdr
= body
;
109 * ieee802_1x_mka_dump_basic_body -
112 ieee802_1x_mka_dump_basic_body(struct ieee802_1x_mka_basic_body
*body
)
119 body_len
= get_mka_param_body_len(body
);
120 wpa_printf(MSG_DEBUG
, "*** MKA Basic Parameter set ***");
121 wpa_printf(MSG_DEBUG
, "\tVersion.......: %d", body
->version
);
122 wpa_printf(MSG_DEBUG
, "\tPriority......: %d", body
->priority
);
123 wpa_printf(MSG_DEBUG
, "\tKeySvr........: %d", body
->key_server
);
124 wpa_printf(MSG_DEBUG
, "\tMACSecDesired.: %d", body
->macsec_desired
);
125 wpa_printf(MSG_DEBUG
, "\tMACSecCapable.: %d", body
->macsec_capability
);
126 wpa_printf(MSG_DEBUG
, "\tBody Length...: %d", (int) body_len
);
127 wpa_printf(MSG_DEBUG
, "\tSCI MAC.......: " MACSTR
,
128 MAC2STR(body
->actor_sci
.addr
));
129 wpa_printf(MSG_DEBUG
, "\tSCI Port .....: %d",
130 be_to_host16(body
->actor_sci
.port
));
131 wpa_hexdump(MSG_DEBUG
, "\tMember Id.....:",
132 body
->actor_mi
, sizeof(body
->actor_mi
));
133 wpa_printf(MSG_DEBUG
, "\tMessage Number: %d",
134 be_to_host32(body
->actor_mn
));
135 wpa_hexdump(MSG_DEBUG
, "\tAlgo Agility..:",
136 body
->algo_agility
, sizeof(body
->algo_agility
));
137 wpa_hexdump_ascii(MSG_DEBUG
, "\tCAK Name......:", body
->ckn
,
138 body_len
+ MKA_HDR_LEN
- sizeof(*body
));
143 * ieee802_1x_mka_dump_peer_body -
146 ieee802_1x_mka_dump_peer_body(struct ieee802_1x_mka_peer_body
*body
)
156 body_len
= get_mka_param_body_len(body
);
157 if (body
->type
== MKA_LIVE_PEER_LIST
) {
158 wpa_printf(MSG_DEBUG
, "*** Live Peer List ***");
159 wpa_printf(MSG_DEBUG
, "\tBody Length...: %d", (int) body_len
);
160 } else if (body
->type
== MKA_POTENTIAL_PEER_LIST
) {
161 wpa_printf(MSG_DEBUG
, "*** Potential Live Peer List ***");
162 wpa_printf(MSG_DEBUG
, "\tBody Length...: %d", (int) body_len
);
165 for (i
= 0; i
< body_len
; i
+= MI_LEN
+ sizeof(mn
)) {
167 os_memcpy(&mn
, mi
+ MI_LEN
, sizeof(mn
));
168 wpa_hexdump_ascii(MSG_DEBUG
, "\tMember Id.....:", mi
, MI_LEN
);
169 wpa_printf(MSG_DEBUG
, "\tMessage Number: %d", be_to_host32(mn
));
175 * ieee802_1x_mka_dump_dist_sak_body -
178 ieee802_1x_mka_dump_dist_sak_body(struct ieee802_1x_mka_dist_sak_body
*body
)
185 body_len
= get_mka_param_body_len(body
);
186 wpa_printf(MSG_INFO
, "*** Distributed SAK ***");
187 wpa_printf(MSG_INFO
, "\tDistributed AN........: %d", body
->dan
);
188 wpa_printf(MSG_INFO
, "\tConfidentiality Offset: %d",
189 body
->confid_offset
);
190 wpa_printf(MSG_INFO
, "\tBody Length...........: %d", (int) body_len
);
194 wpa_printf(MSG_INFO
, "\tKey Number............: %d",
195 be_to_host32(body
->kn
));
196 wpa_hexdump(MSG_INFO
, "\tAES Key Wrap of SAK...:", body
->sak
, 24);
200 static const char * yes_no(int val
)
202 return val
? "Yes" : "No";
207 * ieee802_1x_mka_dump_sak_use_body -
210 ieee802_1x_mka_dump_sak_use_body(struct ieee802_1x_mka_sak_use_body
*body
)
217 body_len
= get_mka_param_body_len(body
);
218 wpa_printf(MSG_DEBUG
, "*** MACsec SAK Use ***");
219 wpa_printf(MSG_DEBUG
, "\tLatest Key AN....: %d", body
->lan
);
220 wpa_printf(MSG_DEBUG
, "\tLatest Key Tx....: %s", yes_no(body
->ltx
));
221 wpa_printf(MSG_DEBUG
, "\tLatest Key Rx....: %s", yes_no(body
->lrx
));
222 wpa_printf(MSG_DEBUG
, "\tOld Key AN....: %d", body
->oan
);
223 wpa_printf(MSG_DEBUG
, "\tOld Key Tx....: %s", yes_no(body
->otx
));
224 wpa_printf(MSG_DEBUG
, "\tOld Key Rx....: %s", yes_no(body
->orx
));
225 wpa_printf(MSG_DEBUG
, "\tPlain Key Tx....: %s", yes_no(body
->ptx
));
226 wpa_printf(MSG_DEBUG
, "\tPlain Key Rx....: %s", yes_no(body
->prx
));
227 wpa_printf(MSG_DEBUG
, "\tDelay Protect....: %s",
228 yes_no(body
->delay_protect
));
229 wpa_printf(MSG_DEBUG
, "\tBody Length......: %d", body_len
);
233 wpa_hexdump(MSG_DEBUG
, "\tKey Server MI....:",
234 body
->lsrv_mi
, sizeof(body
->lsrv_mi
));
235 wpa_printf(MSG_DEBUG
, "\tKey Number.......: %u",
236 be_to_host32(body
->lkn
));
237 wpa_printf(MSG_DEBUG
, "\tLowest PN........: %u",
238 be_to_host32(body
->llpn
));
239 wpa_hexdump_ascii(MSG_DEBUG
, "\tOld Key Server MI....:",
240 body
->osrv_mi
, sizeof(body
->osrv_mi
));
241 wpa_printf(MSG_DEBUG
, "\tOld Key Number.......: %u",
242 be_to_host32(body
->okn
));
243 wpa_printf(MSG_DEBUG
, "\tOld Lowest PN........: %u",
244 be_to_host32(body
->olpn
));
249 * ieee802_1x_kay_get_participant -
251 static struct ieee802_1x_mka_participant
*
252 ieee802_1x_kay_get_participant(struct ieee802_1x_kay
*kay
, const u8
*ckn
)
254 struct ieee802_1x_mka_participant
*participant
;
256 dl_list_for_each(participant
, &kay
->participant_list
,
257 struct ieee802_1x_mka_participant
, list
) {
258 if (os_memcmp(participant
->ckn
.name
, ckn
,
259 participant
->ckn
.len
) == 0)
263 wpa_printf(MSG_DEBUG
, "KaY: participant is not found");
270 * ieee802_1x_kay_get_principal_participant -
272 static struct ieee802_1x_mka_participant
*
273 ieee802_1x_kay_get_principal_participant(struct ieee802_1x_kay
*kay
)
275 struct ieee802_1x_mka_participant
*participant
;
277 dl_list_for_each(participant
, &kay
->participant_list
,
278 struct ieee802_1x_mka_participant
, list
) {
279 if (participant
->principal
)
283 wpa_printf(MSG_DEBUG
, "KaY: principal participant is not founded");
288 static struct ieee802_1x_kay_peer
* get_peer_mi(struct dl_list
*peers
,
291 struct ieee802_1x_kay_peer
*peer
;
293 dl_list_for_each(peer
, peers
, struct ieee802_1x_kay_peer
, list
) {
294 if (os_memcmp(peer
->mi
, mi
, MI_LEN
) == 0)
303 * ieee802_1x_kay_get_potential_peer
305 static struct ieee802_1x_kay_peer
*
306 ieee802_1x_kay_get_potential_peer(
307 struct ieee802_1x_mka_participant
*participant
, const u8
*mi
)
309 return get_peer_mi(&participant
->potential_peers
, mi
);
314 * ieee802_1x_kay_get_live_peer
316 static struct ieee802_1x_kay_peer
*
317 ieee802_1x_kay_get_live_peer(struct ieee802_1x_mka_participant
*participant
,
320 return get_peer_mi(&participant
->live_peers
, mi
);
325 * ieee802_1x_kay_is_in_potential_peer
328 ieee802_1x_kay_is_in_potential_peer(
329 struct ieee802_1x_mka_participant
*participant
, const u8
*mi
)
331 return ieee802_1x_kay_get_potential_peer(participant
, mi
) != NULL
;
336 * ieee802_1x_kay_is_in_live_peer
339 ieee802_1x_kay_is_in_live_peer(
340 struct ieee802_1x_mka_participant
*participant
, const u8
*mi
)
342 return ieee802_1x_kay_get_live_peer(participant
, mi
) != NULL
;
347 * ieee802_1x_kay_is_in_peer
350 ieee802_1x_kay_is_in_peer(struct ieee802_1x_mka_participant
*participant
,
353 return ieee802_1x_kay_is_in_live_peer(participant
, mi
) ||
354 ieee802_1x_kay_is_in_potential_peer(participant
, mi
);
359 * ieee802_1x_kay_get_peer
361 static struct ieee802_1x_kay_peer
*
362 ieee802_1x_kay_get_peer(struct ieee802_1x_mka_participant
*participant
,
365 struct ieee802_1x_kay_peer
*peer
;
367 peer
= ieee802_1x_kay_get_live_peer(participant
, mi
);
371 return ieee802_1x_kay_get_potential_peer(participant
, mi
);
376 * ieee802_1x_kay_get_cipher_suite
378 static struct macsec_ciphersuite
*
379 ieee802_1x_kay_get_cipher_suite(struct ieee802_1x_mka_participant
*participant
,
384 for (i
= 0; i
< CS_TABLE_SIZE
; i
++) {
385 if (os_memcmp(cipher_suite_tbl
[i
].id
, cs_id
, CS_ID_LEN
) == 0)
386 return &cipher_suite_tbl
[i
];
393 static Boolean
sci_equal(const struct ieee802_1x_mka_sci
*a
,
394 const struct ieee802_1x_mka_sci
*b
)
396 return os_memcmp(a
, b
, sizeof(struct ieee802_1x_mka_sci
)) == 0;
401 * ieee802_1x_kay_get_peer_sci
403 static struct ieee802_1x_kay_peer
*
404 ieee802_1x_kay_get_peer_sci(struct ieee802_1x_mka_participant
*participant
,
405 const struct ieee802_1x_mka_sci
*sci
)
407 struct ieee802_1x_kay_peer
*peer
;
409 dl_list_for_each(peer
, &participant
->live_peers
,
410 struct ieee802_1x_kay_peer
, list
) {
411 if (sci_equal(&peer
->sci
, sci
))
415 dl_list_for_each(peer
, &participant
->potential_peers
,
416 struct ieee802_1x_kay_peer
, list
) {
417 if (sci_equal(&peer
->sci
, sci
))
426 * ieee802_1x_kay_init_receive_sa -
428 static struct receive_sa
*
429 ieee802_1x_kay_init_receive_sa(struct receive_sc
*psc
, u8 an
, u32 lowest_pn
,
430 struct data_key
*key
)
432 struct receive_sa
*psa
;
437 psa
= os_zalloc(sizeof(*psa
));
439 wpa_printf(MSG_ERROR
, "%s: out of memory", __func__
);
444 psa
->lowest_pn
= lowest_pn
;
445 psa
->next_pn
= lowest_pn
;
449 os_get_time(&psa
->created_time
);
452 dl_list_add(&psc
->sa_list
, &psa
->list
);
453 wpa_printf(MSG_DEBUG
,
454 "KaY: Create receive SA(AN: %d lowest_pn: %u of SC(channel: %d)",
455 (int) an
, lowest_pn
, psc
->channel
);
462 * ieee802_1x_kay_deinit_receive_sa -
464 static void ieee802_1x_kay_deinit_receive_sa(struct receive_sa
*psa
)
467 wpa_printf(MSG_DEBUG
,
468 "KaY: Delete receive SA(an: %d) of SC(channel: %d)",
469 psa
->an
, psa
->sc
->channel
);
470 dl_list_del(&psa
->list
);
476 * ieee802_1x_kay_init_receive_sc -
478 static struct receive_sc
*
479 ieee802_1x_kay_init_receive_sc(const struct ieee802_1x_mka_sci
*psci
,
482 struct receive_sc
*psc
;
487 psc
= os_zalloc(sizeof(*psc
));
489 wpa_printf(MSG_ERROR
, "%s: out of memory", __func__
);
493 os_memcpy(&psc
->sci
, psci
, sizeof(psc
->sci
));
494 psc
->channel
= channel
;
496 os_get_time(&psc
->created_time
);
497 psc
->receiving
= FALSE
;
499 dl_list_init(&psc
->sa_list
);
500 wpa_printf(MSG_DEBUG
, "KaY: Create receive SC(channel: %d)", channel
);
501 wpa_hexdump(MSG_DEBUG
, "SCI: ", (u8
*)psci
, sizeof(*psci
));
508 * ieee802_1x_kay_deinit_receive_sc -
511 ieee802_1x_kay_deinit_receive_sc(
512 struct ieee802_1x_mka_participant
*participant
, struct receive_sc
*psc
)
514 struct receive_sa
*psa
, *pre_sa
;
516 wpa_printf(MSG_DEBUG
, "KaY: Delete receive SC(channel: %d)",
518 dl_list_for_each_safe(psa
, pre_sa
, &psc
->sa_list
, struct receive_sa
,
520 secy_disable_receive_sa(participant
->kay
, psa
);
521 ieee802_1x_kay_deinit_receive_sa(psa
);
523 dl_list_del(&psc
->list
);
528 static void ieee802_1x_kay_dump_peer(struct ieee802_1x_kay_peer
*peer
)
530 wpa_hexdump(MSG_DEBUG
, "\tMI: ", peer
->mi
, sizeof(peer
->mi
));
531 wpa_printf(MSG_DEBUG
, "\tMN: %d", peer
->mn
);
532 wpa_hexdump(MSG_DEBUG
, "\tSCI Addr: ", peer
->sci
.addr
, ETH_ALEN
);
533 wpa_printf(MSG_DEBUG
, "\tPort: %d", peer
->sci
.port
);
537 static struct ieee802_1x_kay_peer
*
538 ieee802_1x_kay_create_peer(const u8
*mi
, u32 mn
)
540 struct ieee802_1x_kay_peer
*peer
;
542 peer
= os_zalloc(sizeof(*peer
));
544 wpa_printf(MSG_ERROR
, "KaY-%s: out of memory", __func__
);
548 os_memcpy(peer
->mi
, mi
, MI_LEN
);
550 peer
->expire
= time(NULL
) + MKA_LIFE_TIME
/ 1000;
551 peer
->sak_used
= FALSE
;
558 * ieee802_1x_kay_create_live_peer
560 static struct ieee802_1x_kay_peer
*
561 ieee802_1x_kay_create_live_peer(struct ieee802_1x_mka_participant
*participant
,
562 const u8
*mi
, u32 mn
)
564 struct ieee802_1x_kay_peer
*peer
;
565 struct receive_sc
*rxsc
;
568 peer
= ieee802_1x_kay_create_peer(mi
, mn
);
572 os_memcpy(&peer
->sci
, &participant
->current_peer_sci
,
575 secy_get_available_receive_sc(participant
->kay
, &sc_ch
);
577 rxsc
= ieee802_1x_kay_init_receive_sc(&peer
->sci
, sc_ch
);
583 dl_list_add(&participant
->live_peers
, &peer
->list
);
584 dl_list_add(&participant
->rxsc_list
, &rxsc
->list
);
585 secy_create_receive_sc(participant
->kay
, rxsc
);
587 wpa_printf(MSG_DEBUG
, "KaY: Live peer created");
588 ieee802_1x_kay_dump_peer(peer
);
595 * ieee802_1x_kay_create_potential_peer
597 static struct ieee802_1x_kay_peer
*
598 ieee802_1x_kay_create_potential_peer(
599 struct ieee802_1x_mka_participant
*participant
, const u8
*mi
, u32 mn
)
601 struct ieee802_1x_kay_peer
*peer
;
603 peer
= ieee802_1x_kay_create_peer(mi
, mn
);
607 dl_list_add(&participant
->potential_peers
, &peer
->list
);
609 wpa_printf(MSG_DEBUG
, "KaY: potential peer created");
610 ieee802_1x_kay_dump_peer(peer
);
617 * ieee802_1x_kay_move_live_peer
619 static struct ieee802_1x_kay_peer
*
620 ieee802_1x_kay_move_live_peer(struct ieee802_1x_mka_participant
*participant
,
623 struct ieee802_1x_kay_peer
*peer
;
624 struct receive_sc
*rxsc
;
627 peer
= ieee802_1x_kay_get_potential_peer(participant
, mi
);
629 rxsc
= ieee802_1x_kay_init_receive_sc(&participant
->current_peer_sci
,
634 os_memcpy(&peer
->sci
, &participant
->current_peer_sci
,
637 peer
->expire
= time(NULL
) + MKA_LIFE_TIME
/ 1000;
639 wpa_printf(MSG_DEBUG
, "KaY: move potential peer to live peer");
640 ieee802_1x_kay_dump_peer(peer
);
642 dl_list_del(&peer
->list
);
643 dl_list_add_tail(&participant
->live_peers
, &peer
->list
);
645 secy_get_available_receive_sc(participant
->kay
, &sc_ch
);
647 dl_list_add(&participant
->rxsc_list
, &rxsc
->list
);
648 secy_create_receive_sc(participant
->kay
, rxsc
);
656 * ieee802_1x_mka_basic_body_present -
659 ieee802_1x_mka_basic_body_present(
660 struct ieee802_1x_mka_participant
*participant
)
667 * ieee802_1x_mka_basic_body_length -
670 ieee802_1x_mka_basic_body_length(struct ieee802_1x_mka_participant
*participant
)
674 length
= sizeof(struct ieee802_1x_mka_basic_body
);
675 length
+= participant
->ckn
.len
;
676 return (length
+ 0x3) & ~0x3;
681 * ieee802_1x_mka_encode_basic_body
684 ieee802_1x_mka_encode_basic_body(
685 struct ieee802_1x_mka_participant
*participant
,
688 struct ieee802_1x_mka_basic_body
*body
;
689 struct ieee802_1x_kay
*kay
= participant
->kay
;
690 unsigned int length
= ieee802_1x_mka_basic_body_length(participant
);
692 body
= wpabuf_put(buf
, length
);
694 body
->version
= kay
->mka_version
;
695 body
->priority
= kay
->actor_priority
;
696 if (participant
->is_elected
)
697 body
->key_server
= participant
->is_key_server
;
699 body
->key_server
= participant
->can_be_key_server
;
701 body
->macsec_desired
= kay
->macsec_desired
;
702 body
->macsec_capability
= kay
->macsec_capable
;
703 set_mka_param_body_len(body
, length
- MKA_HDR_LEN
);
705 os_memcpy(body
->actor_sci
.addr
, kay
->actor_sci
.addr
,
706 sizeof(kay
->actor_sci
.addr
));
707 body
->actor_sci
.port
= kay
->actor_sci
.port
;
709 os_memcpy(body
->actor_mi
, participant
->mi
, sizeof(body
->actor_mi
));
710 participant
->mn
= participant
->mn
+ 1;
711 body
->actor_mn
= host_to_be32(participant
->mn
);
712 os_memcpy(body
->algo_agility
, participant
->kay
->algo_agility
,
713 sizeof(body
->algo_agility
));
715 os_memcpy(body
->ckn
, participant
->ckn
.name
, participant
->ckn
.len
);
717 ieee802_1x_mka_dump_basic_body(body
);
724 * ieee802_1x_mka_decode_basic_body -
726 static struct ieee802_1x_mka_participant
*
727 ieee802_1x_mka_decode_basic_body(struct ieee802_1x_kay
*kay
, const u8
*mka_msg
,
730 struct ieee802_1x_mka_participant
*participant
;
731 const struct ieee802_1x_mka_basic_body
*body
;
732 struct ieee802_1x_kay_peer
*peer
;
734 body
= (const struct ieee802_1x_mka_basic_body
*) mka_msg
;
736 if (body
->version
> MKA_VERSION_ID
) {
737 wpa_printf(MSG_DEBUG
,
738 "KaY: peer's version(%d) greater than mka current version(%d)",
739 body
->version
, MKA_VERSION_ID
);
741 if (kay
->is_obliged_key_server
&& body
->key_server
) {
742 wpa_printf(MSG_DEBUG
, "I must be as key server");
746 participant
= ieee802_1x_kay_get_participant(kay
, body
->ckn
);
748 wpa_printf(MSG_DEBUG
, "Peer is not included in my CA");
752 /* If the peer's MI is my MI, I will choose new MI */
753 if (os_memcmp(body
->actor_mi
, participant
->mi
, MI_LEN
) == 0) {
754 if (os_get_random(participant
->mi
, sizeof(participant
->mi
)) < 0)
759 os_memcpy(participant
->current_peer_id
.mi
, body
->actor_mi
, MI_LEN
);
760 participant
->current_peer_id
.mn
= body
->actor_mn
;
761 os_memcpy(participant
->current_peer_sci
.addr
, body
->actor_sci
.addr
,
762 sizeof(participant
->current_peer_sci
.addr
));
763 participant
->current_peer_sci
.port
= body
->actor_sci
.port
;
766 peer
= ieee802_1x_kay_get_peer(participant
, body
->actor_mi
);
768 /* Check duplicated SCI */
769 /* TODO: What policy should be applied to detect duplicated SCI
770 * is active attacker or a valid peer whose MI is be changed?
772 peer
= ieee802_1x_kay_get_peer_sci(participant
,
775 wpa_printf(MSG_WARNING
,
776 "KaY: duplicated SCI detected, Maybe active attacker");
777 dl_list_del(&peer
->list
);
781 peer
= ieee802_1x_kay_create_potential_peer(
782 participant
, body
->actor_mi
,
783 be_to_host32(body
->actor_mn
));
787 peer
->macsec_desired
= body
->macsec_desired
;
788 peer
->macsec_capability
= body
->macsec_capability
;
789 peer
->is_key_server
= (Boolean
) body
->key_server
;
790 peer
->key_server_priority
= body
->priority
;
791 } else if (peer
->mn
< be_to_host32(body
->actor_mn
)) {
792 peer
->mn
= be_to_host32(body
->actor_mn
);
793 peer
->expire
= time(NULL
) + MKA_LIFE_TIME
/ 1000;
794 peer
->macsec_desired
= body
->macsec_desired
;
795 peer
->macsec_capability
= body
->macsec_capability
;
796 peer
->is_key_server
= (Boolean
) body
->key_server
;
797 peer
->key_server_priority
= body
->priority
;
799 wpa_printf(MSG_WARNING
, "KaY: The peer MN have received");
808 * ieee802_1x_mka_live_peer_body_present
811 ieee802_1x_mka_live_peer_body_present(
812 struct ieee802_1x_mka_participant
*participant
)
814 return !dl_list_empty(&participant
->live_peers
);
819 * ieee802_1x_kay_get_live_peer_length
822 ieee802_1x_mka_get_live_peer_length(
823 struct ieee802_1x_mka_participant
*participant
)
825 int len
= MKA_HDR_LEN
;
826 struct ieee802_1x_kay_peer
*peer
;
828 dl_list_for_each(peer
, &participant
->live_peers
,
829 struct ieee802_1x_kay_peer
, list
)
830 len
+= sizeof(struct ieee802_1x_mka_peer_id
);
832 return (len
+ 0x3) & ~0x3;
837 * ieee802_1x_mka_encode_live_peer_body -
840 ieee802_1x_mka_encode_live_peer_body(
841 struct ieee802_1x_mka_participant
*participant
,
844 struct ieee802_1x_mka_peer_body
*body
;
845 struct ieee802_1x_kay_peer
*peer
;
847 struct ieee802_1x_mka_peer_id
*body_peer
;
849 length
= ieee802_1x_mka_get_live_peer_length(participant
);
850 body
= wpabuf_put(buf
, sizeof(struct ieee802_1x_mka_peer_body
));
852 body
->type
= MKA_LIVE_PEER_LIST
;
853 set_mka_param_body_len(body
, length
- MKA_HDR_LEN
);
855 dl_list_for_each(peer
, &participant
->live_peers
,
856 struct ieee802_1x_kay_peer
, list
) {
857 body_peer
= wpabuf_put(buf
,
858 sizeof(struct ieee802_1x_mka_peer_id
));
859 os_memcpy(body_peer
->mi
, peer
->mi
, MI_LEN
);
860 body_peer
->mn
= host_to_be32(peer
->mn
);
864 ieee802_1x_mka_dump_peer_body(body
);
869 * ieee802_1x_mka_potential_peer_body_present
872 ieee802_1x_mka_potential_peer_body_present(
873 struct ieee802_1x_mka_participant
*participant
)
875 return !dl_list_empty(&participant
->potential_peers
);
880 * ieee802_1x_kay_get_potential_peer_length
883 ieee802_1x_mka_get_potential_peer_length(
884 struct ieee802_1x_mka_participant
*participant
)
886 int len
= MKA_HDR_LEN
;
887 struct ieee802_1x_kay_peer
*peer
;
889 dl_list_for_each(peer
, &participant
->potential_peers
,
890 struct ieee802_1x_kay_peer
, list
)
891 len
+= sizeof(struct ieee802_1x_mka_peer_id
);
893 return (len
+ 0x3) & ~0x3;
898 * ieee802_1x_mka_encode_potential_peer_body -
901 ieee802_1x_mka_encode_potential_peer_body(
902 struct ieee802_1x_mka_participant
*participant
,
905 struct ieee802_1x_mka_peer_body
*body
;
906 struct ieee802_1x_kay_peer
*peer
;
908 struct ieee802_1x_mka_peer_id
*body_peer
;
910 length
= ieee802_1x_mka_get_potential_peer_length(participant
);
911 body
= wpabuf_put(buf
, sizeof(struct ieee802_1x_mka_peer_body
));
913 body
->type
= MKA_POTENTIAL_PEER_LIST
;
914 set_mka_param_body_len(body
, length
- MKA_HDR_LEN
);
916 dl_list_for_each(peer
, &participant
->potential_peers
,
917 struct ieee802_1x_kay_peer
, list
) {
918 body_peer
= wpabuf_put(buf
,
919 sizeof(struct ieee802_1x_mka_peer_id
));
920 os_memcpy(body_peer
->mi
, peer
->mi
, MI_LEN
);
921 body_peer
->mn
= host_to_be32(peer
->mn
);
925 ieee802_1x_mka_dump_peer_body(body
);
931 * ieee802_1x_mka_i_in_peerlist -
934 ieee802_1x_mka_i_in_peerlist(struct ieee802_1x_mka_participant
*participant
,
935 const u8
*mka_msg
, size_t msg_len
)
937 Boolean included
= FALSE
;
938 struct ieee802_1x_mka_hdr
*hdr
;
950 while (left_len
> (MKA_HDR_LEN
+ DEFAULT_ICV_LEN
)) {
951 hdr
= (struct ieee802_1x_mka_hdr
*) pos
;
952 body_len
= get_mka_param_body_len(hdr
);
953 body_type
= get_mka_param_body_type(hdr
);
955 if (body_type
!= MKA_LIVE_PEER_LIST
&&
956 body_type
!= MKA_POTENTIAL_PEER_LIST
)
959 ieee802_1x_mka_dump_peer_body(
960 (struct ieee802_1x_mka_peer_body
*)pos
);
962 if (left_len
< (MKA_HDR_LEN
+ body_len
+ DEFAULT_ICV_LEN
)) {
963 wpa_printf(MSG_ERROR
,
964 "KaY: MKA Peer Packet Body Length (%d bytes) is less than the Parameter Set Header Length (%d bytes) + the Parameter Set Body Length (%d bytes) + %d bytes of ICV",
965 (int) left_len
, (int) MKA_HDR_LEN
,
966 (int) body_len
, DEFAULT_ICV_LEN
);
970 if ((body_len
% 16) != 0) {
971 wpa_printf(MSG_ERROR
,
972 "KaY: MKA Peer Packet Body Length (%d bytes) should multiple of 16 octets",
977 for (i
= 0; i
< body_len
; i
+= MI_LEN
+ sizeof(peer_mn
)) {
978 peer_mi
= MKA_HDR_LEN
+ pos
+ i
;
979 os_memcpy(&_peer_mn
, peer_mi
+ MI_LEN
,
981 peer_mn
= be_to_host32(_peer_mn
);
982 if (os_memcmp(peer_mi
, participant
->mi
, MI_LEN
) == 0 &&
983 peer_mn
== participant
->mn
) {
993 left_len
-= body_len
+ MKA_HDR_LEN
;
994 pos
+= body_len
+ MKA_HDR_LEN
;
1002 * ieee802_1x_mka_decode_live_peer_body -
1004 static int ieee802_1x_mka_decode_live_peer_body(
1005 struct ieee802_1x_mka_participant
*participant
,
1006 const u8
*peer_msg
, size_t msg_len
)
1008 const struct ieee802_1x_mka_hdr
*hdr
;
1009 struct ieee802_1x_kay_peer
*peer
;
1015 Boolean is_included
;
1017 is_included
= ieee802_1x_kay_is_in_live_peer(
1018 participant
, participant
->current_peer_id
.mi
);
1020 hdr
= (const struct ieee802_1x_mka_hdr
*) peer_msg
;
1021 body_len
= get_mka_param_body_len(hdr
);
1022 if (body_len
% 16 != 0) {
1023 wpa_printf(MSG_ERROR
,
1024 "KaY: MKA Peer Packet Body Length (%zu bytes) should be a multiple of 16 octets",
1029 for (i
= 0; i
< body_len
; i
+= MI_LEN
+ sizeof(peer_mn
)) {
1030 peer_mi
= MKA_HDR_LEN
+ peer_msg
+ i
;
1031 os_memcpy(&_peer_mn
, peer_mi
+ MI_LEN
, sizeof(_peer_mn
));
1032 peer_mn
= be_to_host32(_peer_mn
);
1035 if (os_memcmp(peer_mi
, participant
->mi
, MI_LEN
) == 0) {
1036 /* My message id is used by other participant */
1037 if (peer_mn
> participant
->mn
) {
1038 if (os_get_random(participant
->mi
,
1039 sizeof(participant
->mi
)) < 0)
1040 wpa_printf(MSG_DEBUG
,
1041 "KaY: Could not update mi");
1042 participant
->mn
= 0;
1049 peer
= ieee802_1x_kay_get_peer(participant
, peer_mi
);
1052 peer
->expire
= time(NULL
) + MKA_LIFE_TIME
/ 1000;
1054 if (!ieee802_1x_kay_create_potential_peer(
1055 participant
, peer_mi
, peer_mn
)) {
1066 * ieee802_1x_mka_decode_potential_peer_body -
1069 ieee802_1x_mka_decode_potential_peer_body(
1070 struct ieee802_1x_mka_participant
*participant
,
1071 const u8
*peer_msg
, size_t msg_len
)
1073 struct ieee802_1x_mka_hdr
*hdr
;
1080 hdr
= (struct ieee802_1x_mka_hdr
*) peer_msg
;
1081 body_len
= get_mka_param_body_len(hdr
);
1082 if (body_len
% 16 != 0) {
1083 wpa_printf(MSG_ERROR
,
1084 "KaY: MKA Peer Packet Body Length (%zu bytes) should be a multiple of 16 octets",
1089 for (i
= 0; i
< body_len
; i
+= MI_LEN
+ sizeof(peer_mn
)) {
1090 peer_mi
= MKA_HDR_LEN
+ peer_msg
+ i
;
1091 os_memcpy(&_peer_mn
, peer_mi
+ MI_LEN
, sizeof(_peer_mn
));
1092 peer_mn
= be_to_host32(_peer_mn
);
1095 if (os_memcmp(peer_mi
, participant
->mi
, MI_LEN
) == 0) {
1096 /* My message id is used by other participant */
1097 if (peer_mn
> participant
->mn
) {
1098 if (os_get_random(participant
->mi
,
1099 sizeof(participant
->mi
)) < 0)
1100 wpa_printf(MSG_DEBUG
,
1101 "KaY: Could not update mi");
1102 participant
->mn
= 0;
1113 * ieee802_1x_mka_sak_use_body_present
1116 ieee802_1x_mka_sak_use_body_present(
1117 struct ieee802_1x_mka_participant
*participant
)
1119 if (participant
->to_use_sak
)
1127 * ieee802_1x_mka_get_sak_use_length
1130 ieee802_1x_mka_get_sak_use_length(
1131 struct ieee802_1x_mka_participant
*participant
)
1133 int length
= MKA_HDR_LEN
;
1135 if (participant
->kay
->macsec_desired
&& participant
->advised_desired
)
1136 length
= sizeof(struct ieee802_1x_mka_sak_use_body
);
1138 length
= MKA_HDR_LEN
;
1140 length
= (length
+ 0x3) & ~0x3;
1150 ieee802_1x_mka_get_lpn(struct ieee802_1x_mka_participant
*principal
,
1151 struct ieee802_1x_mka_ki
*ki
)
1153 struct receive_sa
*rxsa
;
1154 struct receive_sc
*rxsc
;
1157 dl_list_for_each(rxsc
, &principal
->rxsc_list
, struct receive_sc
, list
) {
1158 dl_list_for_each(rxsa
, &rxsc
->sa_list
, struct receive_sa
, list
)
1160 if (is_ki_equal(&rxsa
->pkey
->key_identifier
, ki
)) {
1161 secy_get_receive_lowest_pn(principal
->kay
,
1164 lpn
= lpn
> rxsa
->lowest_pn
?
1165 lpn
: rxsa
->lowest_pn
;
1179 * ieee802_1x_mka_encode_sak_use_body -
1182 ieee802_1x_mka_encode_sak_use_body(
1183 struct ieee802_1x_mka_participant
*participant
,
1186 struct ieee802_1x_mka_sak_use_body
*body
;
1187 unsigned int length
;
1190 length
= ieee802_1x_mka_get_sak_use_length(participant
);
1191 body
= wpabuf_put(buf
, length
);
1193 body
->type
= MKA_SAK_USE
;
1194 set_mka_param_body_len(body
, length
- MKA_HDR_LEN
);
1196 if (length
== MKA_HDR_LEN
) {
1202 body
->delay_protect
= FALSE
;
1206 /* data protect, lowest accept packet number */
1207 body
->delay_protect
= participant
->kay
->macsec_replay_protect
;
1208 pn
= ieee802_1x_mka_get_lpn(participant
, &participant
->lki
);
1209 if (pn
> participant
->kay
->pn_exhaustion
) {
1210 wpa_printf(MSG_WARNING
, "KaY: My LPN exhaustion");
1211 if (participant
->is_key_server
)
1212 participant
->new_sak
= TRUE
;
1215 body
->llpn
= host_to_be32(pn
);
1216 pn
= ieee802_1x_mka_get_lpn(participant
, &participant
->oki
);
1217 body
->olpn
= host_to_be32(pn
);
1219 /* plain tx, plain rx */
1220 if (participant
->kay
->macsec_protect
)
1225 if (participant
->kay
->macsec_validate
== Strict
)
1230 /* latest key: rx, tx, key server member identifier key number */
1231 body
->lan
= participant
->lan
;
1232 os_memcpy(body
->lsrv_mi
, participant
->lki
.mi
,
1233 sizeof(body
->lsrv_mi
));
1234 body
->lkn
= host_to_be32(participant
->lki
.kn
);
1235 body
->lrx
= participant
->lrx
;
1236 body
->ltx
= participant
->ltx
;
1238 /* old key: rx, tx, key server member identifier key number */
1239 body
->oan
= participant
->oan
;
1240 if (participant
->oki
.kn
!= participant
->lki
.kn
&&
1241 participant
->oki
.kn
!= 0) {
1244 os_memcpy(body
->osrv_mi
, participant
->oki
.mi
,
1245 sizeof(body
->osrv_mi
));
1246 body
->okn
= host_to_be32(participant
->oki
.kn
);
1252 /* set CP's variable */
1254 if (!participant
->kay
->tx_enable
)
1255 participant
->kay
->tx_enable
= TRUE
;
1257 if (!participant
->kay
->port_enable
)
1258 participant
->kay
->port_enable
= TRUE
;
1261 if (!participant
->kay
->rx_enable
)
1262 participant
->kay
->rx_enable
= TRUE
;
1265 ieee802_1x_mka_dump_sak_use_body(body
);
1271 * ieee802_1x_mka_decode_sak_use_body -
1274 ieee802_1x_mka_decode_sak_use_body(
1275 struct ieee802_1x_mka_participant
*participant
,
1276 const u8
*mka_msg
, size_t msg_len
)
1278 struct ieee802_1x_mka_hdr
*hdr
;
1279 struct ieee802_1x_mka_sak_use_body
*body
;
1280 struct ieee802_1x_kay_peer
*peer
;
1281 struct transmit_sa
*txsa
;
1282 struct data_key
*sa_key
= NULL
;
1284 struct ieee802_1x_mka_ki ki
;
1286 Boolean all_receiving
;
1289 if (!participant
->principal
) {
1290 wpa_printf(MSG_WARNING
, "KaY: Participant is not principal");
1293 peer
= ieee802_1x_kay_get_live_peer(participant
,
1294 participant
->current_peer_id
.mi
);
1296 wpa_printf(MSG_WARNING
, "KaY: the peer is not my live peer");
1300 hdr
= (struct ieee802_1x_mka_hdr
*) mka_msg
;
1301 body_len
= get_mka_param_body_len(hdr
);
1302 body
= (struct ieee802_1x_mka_sak_use_body
*) mka_msg
;
1303 ieee802_1x_mka_dump_sak_use_body(body
);
1305 if ((body_len
!= 0) && (body_len
< 40)) {
1306 wpa_printf(MSG_ERROR
,
1307 "KaY: MKA Use SAK Packet Body Length (%d bytes) should be 0, 40, or more octets",
1312 /* TODO: what action should I take when peer does not support MACsec */
1313 if (body_len
== 0) {
1314 wpa_printf(MSG_WARNING
, "KaY: Peer does not support MACsec");
1318 /* TODO: when the plain tx or rx of peer is true, should I change
1319 * the attribute of controlled port
1322 wpa_printf(MSG_WARNING
, "KaY: peer's plain rx are TRUE");
1325 wpa_printf(MSG_WARNING
, "KaY: peer's plain tx are TRUE");
1327 /* check latest key is valid */
1328 if (body
->ltx
|| body
->lrx
) {
1330 os_memcpy(ki
.mi
, body
->lsrv_mi
, sizeof(ki
.mi
));
1331 ki
.kn
= be_to_host32(body
->lkn
);
1332 dl_list_for_each(sa_key
, &participant
->sak_list
,
1333 struct data_key
, list
) {
1334 if (is_ki_equal(&sa_key
->key_identifier
, &ki
)) {
1340 wpa_printf(MSG_WARNING
, "KaY: Latest key is invalid");
1343 if (os_memcmp(participant
->lki
.mi
, body
->lsrv_mi
,
1344 sizeof(participant
->lki
.mi
)) == 0 &&
1345 be_to_host32(body
->lkn
) == participant
->lki
.kn
&&
1346 body
->lan
== participant
->lan
) {
1347 peer
->sak_used
= TRUE
;
1349 if (body
->ltx
&& peer
->is_key_server
) {
1350 ieee802_1x_cp_set_servertransmitting(
1351 participant
->kay
->cp
, TRUE
);
1352 ieee802_1x_cp_sm_step(participant
->kay
->cp
);
1356 /* check old key is valid */
1357 if (body
->otx
|| body
->orx
) {
1358 if (os_memcmp(participant
->oki
.mi
, body
->osrv_mi
,
1359 sizeof(participant
->oki
.mi
)) != 0 ||
1360 be_to_host32(body
->okn
) != participant
->oki
.kn
||
1361 body
->oan
!= participant
->oan
) {
1362 wpa_printf(MSG_WARNING
, "KaY: Old key is invalid");
1367 /* TODO: how to set the MACsec hardware when delay_protect is true */
1368 if (body
->delay_protect
&&
1369 (!be_to_host32(body
->llpn
) || !be_to_host32(body
->olpn
))) {
1370 wpa_printf(MSG_WARNING
,
1371 "KaY: Lowest packet number should greater than 0 when delay_protect is TRUE");
1375 /* check all live peer have used the sak for receiving sa */
1376 all_receiving
= TRUE
;
1377 dl_list_for_each(peer
, &participant
->live_peers
,
1378 struct ieee802_1x_kay_peer
, list
) {
1379 if (!peer
->sak_used
) {
1380 all_receiving
= FALSE
;
1384 if (all_receiving
) {
1385 participant
->to_dist_sak
= FALSE
;
1386 ieee802_1x_cp_set_allreceiving(participant
->kay
->cp
, TRUE
);
1387 ieee802_1x_cp_sm_step(participant
->kay
->cp
);
1390 /* if i'm key server, and detects peer member pn exhaustion, rekey.*/
1391 lpn
= be_to_host32(body
->llpn
);
1392 if (lpn
> participant
->kay
->pn_exhaustion
) {
1393 if (participant
->is_key_server
) {
1394 participant
->new_sak
= TRUE
;
1395 wpa_printf(MSG_WARNING
, "KaY: Peer LPN exhaustion");
1400 dl_list_for_each(txsa
, &participant
->txsc
->sa_list
,
1401 struct transmit_sa
, list
) {
1402 if (sa_key
!= NULL
&& txsa
->pkey
== sa_key
) {
1408 wpa_printf(MSG_WARNING
, "KaY: Can't find txsa");
1412 /* FIXME: Secy creates txsa with default npn. If MKA detected Latest Key
1413 * npn is larger than txsa's npn, set it to txsa.
1415 secy_get_transmit_next_pn(participant
->kay
, txsa
);
1416 if (lpn
> txsa
->next_pn
) {
1417 secy_set_transmit_next_pn(participant
->kay
, txsa
);
1418 wpa_printf(MSG_INFO
, "KaY: update lpn =0x%x", lpn
);
1426 * ieee802_1x_mka_dist_sak_body_present
1429 ieee802_1x_mka_dist_sak_body_present(
1430 struct ieee802_1x_mka_participant
*participant
)
1432 if (!participant
->to_dist_sak
|| !participant
->new_key
)
1440 * ieee802_1x_kay_get_dist_sak_length
1443 ieee802_1x_mka_get_dist_sak_length(
1444 struct ieee802_1x_mka_participant
*participant
)
1447 int cs_index
= participant
->kay
->macsec_csindex
;
1449 if (participant
->advised_desired
) {
1450 length
= sizeof(struct ieee802_1x_mka_dist_sak_body
);
1451 if (cs_index
!= DEFAULT_CS_INDEX
)
1452 length
+= CS_ID_LEN
;
1454 length
+= cipher_suite_tbl
[cs_index
].sak_len
+ 8;
1456 length
= MKA_HDR_LEN
;
1458 length
= (length
+ 0x3) & ~0x3;
1465 * ieee802_1x_mka_encode_dist_sak_body -
1468 ieee802_1x_mka_encode_dist_sak_body(
1469 struct ieee802_1x_mka_participant
*participant
,
1472 struct ieee802_1x_mka_dist_sak_body
*body
;
1473 struct data_key
*sak
;
1474 unsigned int length
;
1478 length
= ieee802_1x_mka_get_dist_sak_length(participant
);
1479 body
= wpabuf_put(buf
, length
);
1480 body
->type
= MKA_DISTRIBUTED_SAK
;
1481 set_mka_param_body_len(body
, length
- MKA_HDR_LEN
);
1482 if (length
== MKA_HDR_LEN
) {
1483 body
->confid_offset
= 0;
1488 sak
= participant
->new_key
;
1489 body
->confid_offset
= sak
->confidentiality_offset
;
1490 body
->dan
= sak
->an
;
1491 body
->kn
= host_to_be32(sak
->key_identifier
.kn
);
1492 cs_index
= participant
->kay
->macsec_csindex
;
1494 if (cs_index
!= DEFAULT_CS_INDEX
) {
1495 os_memcpy(body
->sak
, cipher_suite_tbl
[cs_index
].id
, CS_ID_LEN
);
1496 sak_pos
= CS_ID_LEN
;
1498 if (aes_wrap(participant
->kek
.key
, 16,
1499 cipher_suite_tbl
[cs_index
].sak_len
/ 8,
1500 sak
->key
, body
->sak
+ sak_pos
)) {
1501 wpa_printf(MSG_ERROR
, "KaY: AES wrap failed");
1505 ieee802_1x_mka_dump_dist_sak_body(body
);
1512 * ieee802_1x_kay_init_data_key -
1514 static struct data_key
*
1515 ieee802_1x_kay_init_data_key(const struct key_conf
*conf
)
1517 struct data_key
*pkey
;
1522 pkey
= os_zalloc(sizeof(*pkey
));
1524 wpa_printf(MSG_ERROR
, "%s: out of memory", __func__
);
1528 pkey
->key
= os_zalloc(conf
->key_len
);
1529 if (pkey
->key
== NULL
) {
1530 wpa_printf(MSG_ERROR
, "%s: out of memory", __func__
);
1535 os_memcpy(pkey
->key
, conf
->key
, conf
->key_len
);
1536 os_memcpy(&pkey
->key_identifier
, &conf
->ki
,
1537 sizeof(pkey
->key_identifier
));
1538 pkey
->confidentiality_offset
= conf
->offset
;
1539 pkey
->an
= conf
->an
;
1540 pkey
->transmits
= conf
->tx
;
1541 pkey
->receives
= conf
->rx
;
1542 os_get_time(&pkey
->created_time
);
1551 * ieee802_1x_kay_decode_dist_sak_body -
1554 ieee802_1x_mka_decode_dist_sak_body(
1555 struct ieee802_1x_mka_participant
*participant
,
1556 const u8
*mka_msg
, size_t msg_len
)
1558 struct ieee802_1x_mka_hdr
*hdr
;
1559 struct ieee802_1x_mka_dist_sak_body
*body
;
1560 struct ieee802_1x_kay_peer
*peer
;
1561 struct macsec_ciphersuite
*cs
;
1563 struct key_conf
*conf
;
1564 struct data_key
*sa_key
= NULL
;
1565 struct ieee802_1x_mka_ki sak_ki
;
1570 hdr
= (struct ieee802_1x_mka_hdr
*) mka_msg
;
1571 body_len
= get_mka_param_body_len(hdr
);
1572 if ((body_len
!= 0) && (body_len
!= 28) && (body_len
< 36)) {
1573 wpa_printf(MSG_ERROR
,
1574 "KaY: MKA Use SAK Packet Body Length (%d bytes) should be 0, 28, 36, or more octets",
1579 if (!participant
->principal
) {
1580 wpa_printf(MSG_ERROR
,
1581 "KaY: I can't accept the distributed SAK as I am not principal");
1584 if (participant
->is_key_server
) {
1585 wpa_printf(MSG_ERROR
,
1586 "KaY: I can't accept the distributed SAK as myself is key server ");
1589 if (!participant
->kay
->macsec_desired
||
1590 participant
->kay
->macsec_capable
== MACSEC_CAP_NOT_IMPLEMENTED
) {
1591 wpa_printf(MSG_ERROR
,
1592 "KaY: I am not MACsec-desired or without MACsec capable");
1596 peer
= ieee802_1x_kay_get_live_peer(participant
,
1597 participant
->current_peer_id
.mi
);
1599 wpa_printf(MSG_ERROR
,
1600 "KaY: The key server is not in my live peers list");
1603 if (!sci_equal(&participant
->kay
->key_server_sci
, &peer
->sci
)) {
1604 wpa_printf(MSG_ERROR
, "KaY: The key server is not elected");
1607 if (body_len
== 0) {
1608 participant
->kay
->authenticated
= TRUE
;
1609 participant
->kay
->secured
= FALSE
;
1610 participant
->kay
->failed
= FALSE
;
1611 participant
->advised_desired
= FALSE
;
1612 ieee802_1x_cp_connect_authenticated(participant
->kay
->cp
);
1613 ieee802_1x_cp_sm_step(participant
->kay
->cp
);
1614 wpa_printf(MSG_WARNING
, "KaY:The Key server advise no MACsec");
1615 participant
->to_use_sak
= TRUE
;
1618 participant
->advised_desired
= TRUE
;
1619 participant
->kay
->authenticated
= FALSE
;
1620 participant
->kay
->secured
= TRUE
;
1621 participant
->kay
->failed
= FALSE
;
1622 ieee802_1x_cp_connect_secure(participant
->kay
->cp
);
1623 ieee802_1x_cp_sm_step(participant
->kay
->cp
);
1625 body
= (struct ieee802_1x_mka_dist_sak_body
*)mka_msg
;
1626 ieee802_1x_mka_dump_dist_sak_body(body
);
1627 dl_list_for_each(sa_key
, &participant
->sak_list
, struct data_key
, list
)
1629 if (os_memcmp(sa_key
->key_identifier
.mi
,
1630 participant
->current_peer_id
.mi
, MI_LEN
) == 0 &&
1631 sa_key
->key_identifier
.kn
== be_to_host32(body
->kn
)) {
1632 wpa_printf(MSG_WARNING
, "KaY:The Key has installed");
1636 if (body_len
== 28) {
1637 sak_len
= DEFAULT_SA_KEY_LEN
;
1638 wrap_sak
= body
->sak
;
1639 participant
->kay
->macsec_csindex
= DEFAULT_CS_INDEX
;
1641 cs
= ieee802_1x_kay_get_cipher_suite(participant
, body
->sak
);
1643 wpa_printf(MSG_ERROR
,
1644 "KaY: I can't support the Cipher Suite advised by key server");
1647 sak_len
= cs
->sak_len
;
1648 wrap_sak
= body
->sak
+ CS_ID_LEN
;
1649 participant
->kay
->macsec_csindex
= cs
->index
;
1652 unwrap_sak
= os_zalloc(sak_len
);
1654 wpa_printf(MSG_ERROR
, "KaY-%s: Out of memory", __func__
);
1657 if (aes_unwrap(participant
->kek
.key
, 16, sak_len
>> 3, wrap_sak
,
1659 wpa_printf(MSG_ERROR
, "KaY: AES unwrap failed");
1660 os_free(unwrap_sak
);
1663 wpa_hexdump(MSG_DEBUG
, "\tAES Key Unwrap of SAK:", unwrap_sak
, sak_len
);
1665 conf
= os_zalloc(sizeof(*conf
));
1667 wpa_printf(MSG_ERROR
, "KaY-%s: Out of memory", __func__
);
1668 os_free(unwrap_sak
);
1671 conf
->key_len
= sak_len
;
1673 conf
->key
= os_zalloc(conf
->key_len
);
1675 wpa_printf(MSG_ERROR
, "KaY-%s: Out of memory", __func__
);
1676 os_free(unwrap_sak
);
1681 os_memcpy(conf
->key
, unwrap_sak
, conf
->key_len
);
1683 os_memcpy(&sak_ki
.mi
, &participant
->current_peer_id
.mi
,
1685 sak_ki
.kn
= be_to_host32(body
->kn
);
1687 os_memcpy(conf
->ki
.mi
, sak_ki
.mi
, MI_LEN
);
1688 conf
->ki
.kn
= sak_ki
.kn
;
1689 conf
->an
= body
->dan
;
1690 conf
->offset
= body
->confid_offset
;
1694 sa_key
= ieee802_1x_kay_init_data_key(conf
);
1696 os_free(unwrap_sak
);
1702 dl_list_add(&participant
->sak_list
, &sa_key
->list
);
1704 ieee802_1x_cp_set_ciphersuite(
1705 participant
->kay
->cp
,
1706 cipher_suite_tbl
[participant
->kay
->macsec_csindex
].id
);
1707 ieee802_1x_cp_sm_step(participant
->kay
->cp
);
1708 ieee802_1x_cp_set_offset(participant
->kay
->cp
, body
->confid_offset
);
1709 ieee802_1x_cp_sm_step(participant
->kay
->cp
);
1710 ieee802_1x_cp_set_distributedki(participant
->kay
->cp
, &sak_ki
);
1711 ieee802_1x_cp_set_distributedan(participant
->kay
->cp
, body
->dan
);
1712 ieee802_1x_cp_signal_newsak(participant
->kay
->cp
);
1713 ieee802_1x_cp_sm_step(participant
->kay
->cp
);
1715 participant
->to_use_sak
= TRUE
;
1717 os_free(unwrap_sak
);
1726 * ieee802_1x_mka_icv_body_present
1729 ieee802_1x_mka_icv_body_present(struct ieee802_1x_mka_participant
*participant
)
1736 * ieee802_1x_kay_get_icv_length
1739 ieee802_1x_mka_get_icv_length(struct ieee802_1x_mka_participant
*participant
)
1743 length
= sizeof(struct ieee802_1x_mka_icv_body
);
1744 length
+= mka_alg_tbl
[participant
->kay
->mka_algindex
].icv_len
;
1746 return (length
+ 0x3) & ~0x3;
1751 * ieee802_1x_mka_encode_icv_body -
1754 ieee802_1x_mka_encode_icv_body(struct ieee802_1x_mka_participant
*participant
,
1757 struct ieee802_1x_mka_icv_body
*body
;
1758 unsigned int length
;
1759 u8 cmac
[MAX_ICV_LEN
];
1761 length
= ieee802_1x_mka_get_icv_length(participant
);
1762 if (length
!= DEFAULT_ICV_LEN
) {
1763 body
= wpabuf_put(buf
, MKA_HDR_LEN
);
1764 body
->type
= MKA_ICV_INDICATOR
;
1765 set_mka_param_body_len(body
, length
- MKA_HDR_LEN
);
1768 if (mka_alg_tbl
[participant
->kay
->mka_algindex
].icv_hash(
1769 participant
->ick
.key
, wpabuf_head(buf
), buf
->used
, cmac
)) {
1770 wpa_printf(MSG_ERROR
, "KaY, omac1_aes_128 failed");
1774 if (length
!= DEFAULT_ICV_LEN
) {
1775 os_memcpy(wpabuf_put(buf
, length
- MKA_HDR_LEN
), cmac
,
1776 length
- MKA_HDR_LEN
);
1778 os_memcpy(wpabuf_put(buf
, length
), cmac
, length
);
1785 * ieee802_1x_mka_decode_icv_body -
1788 ieee802_1x_mka_decode_icv_body(struct ieee802_1x_mka_participant
*participant
,
1789 const u8
*mka_msg
, size_t msg_len
)
1791 struct ieee802_1x_mka_hdr
*hdr
;
1792 struct ieee802_1x_mka_icv_body
*body
;
1800 while (left_len
> (MKA_HDR_LEN
+ DEFAULT_ICV_LEN
)) {
1801 hdr
= (struct ieee802_1x_mka_hdr
*) pos
;
1802 body_len
= get_mka_param_body_len(hdr
);
1803 body_type
= get_mka_param_body_type(hdr
);
1805 if (left_len
< (body_len
+ MKA_HDR_LEN
))
1808 if (body_type
!= MKA_ICV_INDICATOR
) {
1809 left_len
-= MKA_HDR_LEN
+ body_len
;
1810 pos
+= MKA_HDR_LEN
+ body_len
;
1814 body
= (struct ieee802_1x_mka_icv_body
*)pos
;
1816 < mka_alg_tbl
[participant
->kay
->mka_algindex
].icv_len
) {
1823 return (u8
*) (mka_msg
+ msg_len
- DEFAULT_ICV_LEN
);
1828 * ieee802_1x_mka_decode_dist_cak_body-
1831 ieee802_1x_mka_decode_dist_cak_body(
1832 struct ieee802_1x_mka_participant
*participant
,
1833 const u8
*mka_msg
, size_t msg_len
)
1835 struct ieee802_1x_mka_hdr
*hdr
;
1838 hdr
= (struct ieee802_1x_mka_hdr
*) mka_msg
;
1839 body_len
= get_mka_param_body_len(hdr
);
1840 if (body_len
< 28) {
1841 wpa_printf(MSG_ERROR
,
1842 "KaY: MKA Use SAK Packet Body Length (%d bytes) should be 28 or more octets",
1852 * ieee802_1x_mka_decode_kmd_body -
1855 ieee802_1x_mka_decode_kmd_body(
1856 struct ieee802_1x_mka_participant
*participant
,
1857 const u8
*mka_msg
, size_t msg_len
)
1859 struct ieee802_1x_mka_hdr
*hdr
;
1862 hdr
= (struct ieee802_1x_mka_hdr
*) mka_msg
;
1863 body_len
= get_mka_param_body_len(hdr
);
1865 wpa_printf(MSG_ERROR
,
1866 "KaY: MKA Use SAK Packet Body Length (%d bytes) should be 5 or more octets",
1876 * ieee802_1x_mka_decode_announce_body -
1878 static int ieee802_1x_mka_decode_announce_body(
1879 struct ieee802_1x_mka_participant
*participant
,
1880 const u8
*mka_msg
, size_t msg_len
)
1886 static struct mka_param_body_handler mka_body_handler
[] = {
1887 /* basic parameter set */
1889 ieee802_1x_mka_encode_basic_body
,
1891 ieee802_1x_mka_basic_body_length
,
1892 ieee802_1x_mka_basic_body_present
1895 /* live peer list parameter set */
1897 ieee802_1x_mka_encode_live_peer_body
,
1898 ieee802_1x_mka_decode_live_peer_body
,
1899 ieee802_1x_mka_get_live_peer_length
,
1900 ieee802_1x_mka_live_peer_body_present
1903 /* potential peer list parameter set */
1905 ieee802_1x_mka_encode_potential_peer_body
,
1906 ieee802_1x_mka_decode_potential_peer_body
,
1907 ieee802_1x_mka_get_potential_peer_length
,
1908 ieee802_1x_mka_potential_peer_body_present
1911 /* sak use parameter set */
1913 ieee802_1x_mka_encode_sak_use_body
,
1914 ieee802_1x_mka_decode_sak_use_body
,
1915 ieee802_1x_mka_get_sak_use_length
,
1916 ieee802_1x_mka_sak_use_body_present
1919 /* distribute sak parameter set */
1921 ieee802_1x_mka_encode_dist_sak_body
,
1922 ieee802_1x_mka_decode_dist_sak_body
,
1923 ieee802_1x_mka_get_dist_sak_length
,
1924 ieee802_1x_mka_dist_sak_body_present
1927 /* distribute cak parameter set */
1930 ieee802_1x_mka_decode_dist_cak_body
,
1935 /* kmd parameter set */
1938 ieee802_1x_mka_decode_kmd_body
,
1943 /* announce parameter set */
1946 ieee802_1x_mka_decode_announce_body
,
1951 /* icv parameter set */
1953 ieee802_1x_mka_encode_icv_body
,
1955 ieee802_1x_mka_get_icv_length
,
1956 ieee802_1x_mka_icv_body_present
1962 * ieee802_1x_kay_deinit_data_key -
1964 static void ieee802_1x_kay_deinit_data_key(struct data_key
*pkey
)
1973 dl_list_del(&pkey
->list
);
1980 * ieee802_1x_kay_generate_new_sak -
1983 ieee802_1x_kay_generate_new_sak(struct ieee802_1x_mka_participant
*participant
)
1985 struct data_key
*sa_key
= NULL
;
1986 struct key_conf
*conf
;
1987 struct ieee802_1x_kay_peer
*peer
;
1988 struct ieee802_1x_kay
*kay
= participant
->kay
;
1989 int ctx_len
, ctx_offset
;
1992 /* check condition for generating a fresh SAK:
1993 * must have one live peer
1994 * and MKA life time elapse since last distribution
1995 * or potential peer is empty
1997 if (dl_list_empty(&participant
->live_peers
)) {
1998 wpa_printf(MSG_ERROR
,
1999 "KaY: Live peers list must not empty when generating fresh SAK");
2003 /* FIXME: A fresh SAK not generated until
2004 * the live peer list contains at least one peer and
2005 * MKA life time has elapsed since the prior SAK was first distributed,
2006 * or the Key server's potential peer is empty
2007 * but I can't understand the second item, so
2008 * here only check first item and ingore
2009 * && (!dl_list_empty(&participant->potential_peers))) {
2011 if ((time(NULL
) - kay
->dist_time
) < MKA_LIFE_TIME
/ 1000) {
2012 wpa_printf(MSG_ERROR
,
2013 "KaY: Life time have not elapsed since prior SAK distributed");
2017 conf
= os_zalloc(sizeof(*conf
));
2019 wpa_printf(MSG_ERROR
, "KaY-%s: Out of memory", __func__
);
2022 conf
->key_len
= cipher_suite_tbl
[kay
->macsec_csindex
].sak_len
;
2024 conf
->key
= os_zalloc(conf
->key_len
);
2027 wpa_printf(MSG_ERROR
, "KaY-%s: Out of memory", __func__
);
2031 ctx_len
= conf
->key_len
+ sizeof(kay
->dist_kn
);
2032 dl_list_for_each(peer
, &participant
->live_peers
,
2033 struct ieee802_1x_kay_peer
, list
)
2034 ctx_len
+= sizeof(peer
->mi
);
2035 ctx_len
+= sizeof(participant
->mi
);
2037 context
= os_zalloc(ctx_len
);
2044 if (os_get_random(context
+ ctx_offset
, conf
->key_len
) < 0) {
2050 ctx_offset
+= conf
->key_len
;
2051 dl_list_for_each(peer
, &participant
->live_peers
,
2052 struct ieee802_1x_kay_peer
, list
) {
2053 os_memcpy(context
+ ctx_offset
, peer
->mi
, sizeof(peer
->mi
));
2054 ctx_offset
+= sizeof(peer
->mi
);
2056 os_memcpy(context
+ ctx_offset
, participant
->mi
,
2057 sizeof(participant
->mi
));
2058 ctx_offset
+= sizeof(participant
->mi
);
2059 os_memcpy(context
+ ctx_offset
, &kay
->dist_kn
, sizeof(kay
->dist_kn
));
2061 if (conf
->key_len
== 16) {
2062 ieee802_1x_sak_128bits_aes_cmac(participant
->cak
.key
,
2063 context
, ctx_len
, conf
->key
);
2064 } else if (conf
->key_len
== 32) {
2065 ieee802_1x_sak_128bits_aes_cmac(participant
->cak
.key
,
2066 context
, ctx_len
, conf
->key
);
2068 wpa_printf(MSG_ERROR
, "KaY: SAK Length not support");
2074 wpa_hexdump(MSG_DEBUG
, "KaY: generated new SAK",
2075 conf
->key
, conf
->key_len
);
2077 os_memcpy(conf
->ki
.mi
, participant
->mi
, MI_LEN
);
2078 conf
->ki
.kn
= participant
->kay
->dist_kn
;
2079 conf
->an
= participant
->kay
->dist_an
;
2080 conf
->offset
= kay
->macsec_confidentiality
;
2084 sa_key
= ieee802_1x_kay_init_data_key(conf
);
2091 participant
->new_key
= sa_key
;
2093 dl_list_add(&participant
->sak_list
, &sa_key
->list
);
2094 ieee802_1x_cp_set_ciphersuite(participant
->kay
->cp
,
2095 cipher_suite_tbl
[kay
->macsec_csindex
].id
);
2096 ieee802_1x_cp_sm_step(kay
->cp
);
2097 ieee802_1x_cp_set_offset(kay
->cp
, conf
->offset
);
2098 ieee802_1x_cp_sm_step(kay
->cp
);
2099 ieee802_1x_cp_set_distributedki(kay
->cp
, &conf
->ki
);
2100 ieee802_1x_cp_set_distributedan(kay
->cp
, conf
->an
);
2101 ieee802_1x_cp_signal_newsak(kay
->cp
);
2102 ieee802_1x_cp_sm_step(kay
->cp
);
2104 dl_list_for_each(peer
, &participant
->live_peers
,
2105 struct ieee802_1x_kay_peer
, list
)
2106 peer
->sak_used
= FALSE
;
2108 participant
->kay
->dist_kn
++;
2109 participant
->kay
->dist_an
++;
2110 if (participant
->kay
->dist_an
> 3)
2111 participant
->kay
->dist_an
= 0;
2113 participant
->kay
->dist_time
= time(NULL
);
2123 * ieee802_1x_kay_elect_key_server - elect the key server
2124 * when to elect: whenever the live peers list changes
2127 ieee802_1x_kay_elect_key_server(struct ieee802_1x_mka_participant
*participant
)
2129 struct ieee802_1x_kay_peer
*peer
;
2130 struct ieee802_1x_kay_peer
*key_server
= NULL
;
2131 struct ieee802_1x_kay
*kay
= participant
->kay
;
2132 Boolean i_is_key_server
;
2134 if (participant
->is_obliged_key_server
) {
2135 participant
->new_sak
= TRUE
;
2136 participant
->to_dist_sak
= FALSE
;
2137 ieee802_1x_cp_set_electedself(kay
->cp
, TRUE
);
2141 /* elect the key server among the peers */
2142 dl_list_for_each(peer
, &participant
->live_peers
,
2143 struct ieee802_1x_kay_peer
, list
) {
2144 if (!peer
->is_key_server
)
2152 if (peer
->key_server_priority
<
2153 key_server
->key_server_priority
) {
2155 } else if (peer
->key_server_priority
==
2156 key_server
->key_server_priority
) {
2157 if (os_memcmp(peer
->sci
.addr
, key_server
->sci
.addr
,
2163 /* elect the key server between me and the above elected peer */
2164 i_is_key_server
= FALSE
;
2165 if (key_server
&& participant
->can_be_key_server
) {
2166 if (kay
->actor_priority
2167 < key_server
->key_server_priority
) {
2168 i_is_key_server
= TRUE
;
2169 } else if (kay
->actor_priority
2170 == key_server
->key_server_priority
) {
2171 if (os_memcmp(kay
->actor_sci
.addr
, key_server
->sci
.addr
,
2173 i_is_key_server
= TRUE
;
2175 } else if (participant
->can_be_key_server
) {
2176 i_is_key_server
= TRUE
;
2179 if (i_is_key_server
) {
2180 ieee802_1x_cp_set_electedself(kay
->cp
, TRUE
);
2181 if (!sci_equal(&kay
->key_server_sci
, &kay
->actor_sci
)) {
2182 ieee802_1x_cp_signal_chgdserver(kay
->cp
);
2183 ieee802_1x_cp_sm_step(kay
->cp
);
2186 participant
->is_key_server
= TRUE
;
2187 participant
->principal
= TRUE
;
2188 participant
->new_sak
= TRUE
;
2189 wpa_printf(MSG_DEBUG
, "KaY: I is elected as key server");
2190 participant
->to_dist_sak
= FALSE
;
2191 participant
->is_elected
= TRUE
;
2193 os_memcpy(&kay
->key_server_sci
, &kay
->actor_sci
,
2194 sizeof(kay
->key_server_sci
));
2195 kay
->key_server_priority
= kay
->actor_priority
;
2196 } else if (key_server
) {
2197 ieee802_1x_cp_set_electedself(kay
->cp
, FALSE
);
2198 if (!sci_equal(&kay
->key_server_sci
, &key_server
->sci
)) {
2199 ieee802_1x_cp_signal_chgdserver(kay
->cp
);
2200 ieee802_1x_cp_sm_step(kay
->cp
);
2203 participant
->is_key_server
= FALSE
;
2204 participant
->principal
= TRUE
;
2205 participant
->is_elected
= TRUE
;
2207 os_memcpy(&kay
->key_server_sci
, &key_server
->sci
,
2208 sizeof(kay
->key_server_sci
));
2209 kay
->key_server_priority
= key_server
->key_server_priority
;
2211 participant
->principal
= FALSE
;
2212 participant
->is_key_server
= FALSE
;
2213 participant
->is_elected
= FALSE
;
2221 * ieee802_1x_kay_decide_macsec_use - the key server determinate
2222 * how to use MACsec: whether use MACsec and its capability
2223 * protectFrames will be advised if the key server and one of its live peers are
2224 * MACsec capable and one of those request MACsec protection
2227 ieee802_1x_kay_decide_macsec_use(
2228 struct ieee802_1x_mka_participant
*participant
)
2230 struct ieee802_1x_kay
*kay
= participant
->kay
;
2231 struct ieee802_1x_kay_peer
*peer
;
2232 enum macsec_cap less_capability
;
2235 if (!participant
->is_key_server
)
2238 /* key server self is MACsec-desired and requesting MACsec */
2239 if (!kay
->macsec_desired
) {
2240 participant
->advised_desired
= FALSE
;
2243 if (kay
->macsec_capable
== MACSEC_CAP_NOT_IMPLEMENTED
) {
2244 participant
->advised_desired
= FALSE
;
2247 less_capability
= kay
->macsec_capable
;
2249 /* at least one of peers is MACsec-desired and requesting MACsec */
2251 dl_list_for_each(peer
, &participant
->live_peers
,
2252 struct ieee802_1x_kay_peer
, list
) {
2253 if (!peer
->macsec_desired
)
2256 if (peer
->macsec_capability
== MACSEC_CAP_NOT_IMPLEMENTED
)
2259 less_capability
= (less_capability
< peer
->macsec_capability
) ?
2260 less_capability
: peer
->macsec_capability
;
2265 participant
->advised_desired
= TRUE
;
2266 participant
->advised_capability
= less_capability
;
2267 kay
->authenticated
= FALSE
;
2268 kay
->secured
= TRUE
;
2269 kay
->failed
= FALSE
;
2270 ieee802_1x_cp_connect_secure(kay
->cp
);
2271 ieee802_1x_cp_sm_step(kay
->cp
);
2273 participant
->advised_desired
= FALSE
;
2274 participant
->advised_capability
= MACSEC_CAP_NOT_IMPLEMENTED
;
2275 participant
->to_use_sak
= FALSE
;
2276 kay
->authenticated
= TRUE
;
2277 kay
->secured
= FALSE
;
2278 kay
->failed
= FALSE
;
2287 ieee802_1x_cp_connect_authenticated(kay
->cp
);
2288 ieee802_1x_cp_sm_step(kay
->cp
);
2294 static const u8 pae_group_addr
[ETH_ALEN
] = {
2295 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03
2300 * ieee802_1x_kay_encode_mkpdu -
2303 ieee802_1x_kay_encode_mkpdu(struct ieee802_1x_mka_participant
*participant
,
2304 struct wpabuf
*pbuf
)
2307 struct ieee8023_hdr
*ether_hdr
;
2308 struct ieee802_1x_hdr
*eapol_hdr
;
2310 ether_hdr
= wpabuf_put(pbuf
, sizeof(*ether_hdr
));
2311 os_memcpy(ether_hdr
->dest
, pae_group_addr
, sizeof(ether_hdr
->dest
));
2312 os_memcpy(ether_hdr
->src
, participant
->kay
->actor_sci
.addr
,
2313 sizeof(ether_hdr
->dest
));
2314 ether_hdr
->ethertype
= host_to_be16(ETH_P_EAPOL
);
2316 eapol_hdr
= wpabuf_put(pbuf
, sizeof(*eapol_hdr
));
2317 eapol_hdr
->version
= EAPOL_VERSION
;
2318 eapol_hdr
->type
= IEEE802_1X_TYPE_EAPOL_MKA
;
2319 eapol_hdr
->length
= host_to_be16(pbuf
->size
- pbuf
->used
);
2321 for (i
= 0; i
< ARRAY_SIZE(mka_body_handler
); i
++) {
2322 if (mka_body_handler
[i
].body_present
&&
2323 mka_body_handler
[i
].body_present(participant
)) {
2324 if (mka_body_handler
[i
].body_tx(participant
, pbuf
))
2333 * ieee802_1x_participant_send_mkpdu -
2336 ieee802_1x_participant_send_mkpdu(
2337 struct ieee802_1x_mka_participant
*participant
)
2340 struct ieee802_1x_kay
*kay
= participant
->kay
;
2344 wpa_printf(MSG_DEBUG
, "KaY: to enpacket and send the MKPDU");
2345 length
+= sizeof(struct ieee802_1x_hdr
) + sizeof(struct ieee8023_hdr
);
2346 for (i
= 0; i
< ARRAY_SIZE(mka_body_handler
); i
++) {
2347 if (mka_body_handler
[i
].body_present
&&
2348 mka_body_handler
[i
].body_present(participant
))
2349 length
+= mka_body_handler
[i
].body_length(participant
);
2352 buf
= wpabuf_alloc(length
);
2354 wpa_printf(MSG_ERROR
, "KaY: out of memory");
2358 if (ieee802_1x_kay_encode_mkpdu(participant
, buf
)) {
2359 wpa_printf(MSG_ERROR
, "KaY: encode mkpdu fail!");
2363 l2_packet_send(kay
->l2_mka
, NULL
, 0, wpabuf_head(buf
), wpabuf_len(buf
));
2367 participant
->active
= TRUE
;
2373 static void ieee802_1x_kay_deinit_transmit_sa(struct transmit_sa
*psa
);
2375 * ieee802_1x_participant_timer -
2377 static void ieee802_1x_participant_timer(void *eloop_ctx
, void *timeout_ctx
)
2379 struct ieee802_1x_mka_participant
*participant
;
2380 struct ieee802_1x_kay
*kay
;
2381 struct ieee802_1x_kay_peer
*peer
, *pre_peer
;
2382 time_t now
= time(NULL
);
2384 struct receive_sc
*rxsc
, *pre_rxsc
;
2385 struct transmit_sa
*txsa
, *pre_txsa
;
2387 participant
= (struct ieee802_1x_mka_participant
*)eloop_ctx
;
2388 kay
= participant
->kay
;
2389 if (participant
->cak_life
) {
2390 if (now
> participant
->cak_life
) {
2391 kay
->authenticated
= FALSE
;
2392 kay
->secured
= FALSE
;
2394 ieee802_1x_kay_delete_mka(kay
, &participant
->ckn
);
2399 /* should delete MKA instance if there are not live peers
2400 * when the MKA life elapsed since its creating */
2401 if (participant
->mka_life
) {
2402 if (dl_list_empty(&participant
->live_peers
)) {
2403 if (now
> participant
->mka_life
) {
2404 kay
->authenticated
= FALSE
;
2405 kay
->secured
= FALSE
;
2407 ieee802_1x_kay_delete_mka(kay
,
2412 participant
->mka_life
= 0;
2417 dl_list_for_each_safe(peer
, pre_peer
, &participant
->live_peers
,
2418 struct ieee802_1x_kay_peer
, list
) {
2419 if (now
> peer
->expire
) {
2420 wpa_printf(MSG_DEBUG
, "KaY: Live peer removed");
2421 wpa_hexdump(MSG_DEBUG
, "\tMI: ", peer
->mi
,
2423 wpa_printf(MSG_DEBUG
, "\tMN: %d", peer
->mn
);
2424 dl_list_for_each_safe(rxsc
, pre_rxsc
,
2425 &participant
->rxsc_list
,
2426 struct receive_sc
, list
) {
2427 if (sci_equal(&rxsc
->sci
, &peer
->sci
)) {
2428 secy_delete_receive_sc(kay
, rxsc
);
2429 ieee802_1x_kay_deinit_receive_sc(
2433 dl_list_del(&peer
->list
);
2440 if (dl_list_empty(&participant
->live_peers
)) {
2441 participant
->advised_desired
= FALSE
;
2442 participant
->advised_capability
=
2443 MACSEC_CAP_NOT_IMPLEMENTED
;
2444 participant
->to_use_sak
= FALSE
;
2445 kay
->authenticated
= TRUE
;
2446 kay
->secured
= FALSE
;
2447 kay
->failed
= FALSE
;
2456 dl_list_for_each_safe(txsa
, pre_txsa
,
2457 &participant
->txsc
->sa_list
,
2458 struct transmit_sa
, list
) {
2459 secy_disable_transmit_sa(kay
, txsa
);
2460 ieee802_1x_kay_deinit_transmit_sa(txsa
);
2463 ieee802_1x_cp_connect_authenticated(kay
->cp
);
2464 ieee802_1x_cp_sm_step(kay
->cp
);
2466 ieee802_1x_kay_elect_key_server(participant
);
2467 ieee802_1x_kay_decide_macsec_use(participant
);
2471 dl_list_for_each_safe(peer
, pre_peer
, &participant
->potential_peers
,
2472 struct ieee802_1x_kay_peer
, list
) {
2473 if (now
> peer
->expire
) {
2474 wpa_printf(MSG_DEBUG
, "KaY: Potential peer removed");
2475 wpa_hexdump(MSG_DEBUG
, "\tMI: ", peer
->mi
,
2477 wpa_printf(MSG_DEBUG
, "\tMN: %d", peer
->mn
);
2478 dl_list_del(&peer
->list
);
2483 if (participant
->new_sak
) {
2484 if (!ieee802_1x_kay_generate_new_sak(participant
))
2485 participant
->to_dist_sak
= TRUE
;
2487 participant
->new_sak
= FALSE
;
2490 if (participant
->retry_count
< MAX_RETRY_CNT
) {
2491 ieee802_1x_participant_send_mkpdu(participant
);
2492 participant
->retry_count
++;
2495 eloop_register_timeout(MKA_HELLO_TIME
/ 1000, 0,
2496 ieee802_1x_participant_timer
,
2502 * ieee802_1x_kay_init_transmit_sa -
2504 static struct transmit_sa
*
2505 ieee802_1x_kay_init_transmit_sa(struct transmit_sc
*psc
, u8 an
, u32 next_PN
,
2506 struct data_key
*key
)
2508 struct transmit_sa
*psa
;
2510 key
->tx_latest
= TRUE
;
2511 key
->rx_latest
= TRUE
;
2513 psa
= os_zalloc(sizeof(*psa
));
2515 wpa_printf(MSG_ERROR
, "%s: out of memory", __func__
);
2519 if (key
->confidentiality_offset
>= CONFIDENTIALITY_OFFSET_0
&&
2520 key
->confidentiality_offset
<= CONFIDENTIALITY_OFFSET_50
)
2521 psa
->confidentiality
= TRUE
;
2523 psa
->confidentiality
= FALSE
;
2527 psa
->next_pn
= next_PN
;
2530 os_get_time(&psa
->created_time
);
2531 psa
->in_use
= FALSE
;
2533 dl_list_add(&psc
->sa_list
, &psa
->list
);
2534 wpa_printf(MSG_DEBUG
,
2535 "KaY: Create transmit SA(an: %d, next_PN: %u) of SC(channel: %d)",
2536 (int) an
, next_PN
, psc
->channel
);
2543 * ieee802_1x_kay_deinit_transmit_sa -
2545 static void ieee802_1x_kay_deinit_transmit_sa(struct transmit_sa
*psa
)
2548 wpa_printf(MSG_DEBUG
,
2549 "KaY: Delete transmit SA(an: %d) of SC(channel: %d)",
2550 psa
->an
, psa
->sc
->channel
);
2551 dl_list_del(&psa
->list
);
2557 * init_transmit_sc -
2559 static struct transmit_sc
*
2560 ieee802_1x_kay_init_transmit_sc(const struct ieee802_1x_mka_sci
*sci
,
2563 struct transmit_sc
*psc
;
2565 psc
= os_zalloc(sizeof(*psc
));
2567 wpa_printf(MSG_ERROR
, "%s: out of memory", __func__
);
2570 os_memcpy(&psc
->sci
, sci
, sizeof(psc
->sci
));
2571 psc
->channel
= channel
;
2573 os_get_time(&psc
->created_time
);
2574 psc
->transmitting
= FALSE
;
2575 psc
->encoding_sa
= FALSE
;
2576 psc
->enciphering_sa
= FALSE
;
2578 dl_list_init(&psc
->sa_list
);
2579 wpa_printf(MSG_DEBUG
, "KaY: Create transmit SC(channel: %d)", channel
);
2580 wpa_hexdump(MSG_DEBUG
, "SCI: ", (u8
*)sci
, sizeof(*sci
));
2587 * ieee802_1x_kay_deinit_transmit_sc -
2590 ieee802_1x_kay_deinit_transmit_sc(
2591 struct ieee802_1x_mka_participant
*participant
, struct transmit_sc
*psc
)
2593 struct transmit_sa
*psa
, *tmp
;
2595 wpa_printf(MSG_DEBUG
, "KaY: Delete transmit SC(channel: %d)",
2597 dl_list_for_each_safe(psa
, tmp
, &psc
->sa_list
, struct transmit_sa
,
2599 secy_disable_transmit_sa(participant
->kay
, psa
);
2600 ieee802_1x_kay_deinit_transmit_sa(psa
);
2607 /****************** Interface between CP and KAY *********************/
2609 * ieee802_1x_kay_set_latest_sa_attr -
2611 int ieee802_1x_kay_set_latest_sa_attr(struct ieee802_1x_kay
*kay
,
2612 struct ieee802_1x_mka_ki
*lki
, u8 lan
,
2613 Boolean ltx
, Boolean lrx
)
2615 struct ieee802_1x_mka_participant
*principal
;
2617 principal
= ieee802_1x_kay_get_principal_participant(kay
);
2622 os_memset(&principal
->lki
, 0, sizeof(principal
->lki
));
2624 os_memcpy(&principal
->lki
, lki
, sizeof(principal
->lki
));
2626 principal
->lan
= lan
;
2627 principal
->ltx
= ltx
;
2628 principal
->lrx
= lrx
;
2633 kay
->ltx_kn
= lki
->kn
;
2634 kay
->lrx_kn
= lki
->kn
;
2644 * ieee802_1x_kay_set_old_sa_attr -
2646 int ieee802_1x_kay_set_old_sa_attr(struct ieee802_1x_kay
*kay
,
2647 struct ieee802_1x_mka_ki
*oki
,
2648 u8 oan
, Boolean otx
, Boolean orx
)
2650 struct ieee802_1x_mka_participant
*principal
;
2652 principal
= ieee802_1x_kay_get_principal_participant(kay
);
2657 os_memset(&principal
->oki
, 0, sizeof(principal
->oki
));
2659 os_memcpy(&principal
->oki
, oki
, sizeof(principal
->oki
));
2661 principal
->oan
= oan
;
2662 principal
->otx
= otx
;
2663 principal
->orx
= orx
;
2669 kay
->otx_kn
= oki
->kn
;
2670 kay
->orx_kn
= oki
->kn
;
2680 * ieee802_1x_kay_create_sas -
2682 int ieee802_1x_kay_create_sas(struct ieee802_1x_kay
*kay
,
2683 struct ieee802_1x_mka_ki
*lki
)
2685 struct data_key
*sa_key
, *latest_sak
;
2686 struct ieee802_1x_mka_participant
*principal
;
2687 struct receive_sc
*rxsc
;
2688 struct receive_sa
*rxsa
;
2689 struct transmit_sa
*txsa
;
2691 principal
= ieee802_1x_kay_get_principal_participant(kay
);
2696 dl_list_for_each(sa_key
, &principal
->sak_list
, struct data_key
, list
) {
2697 if (is_ki_equal(&sa_key
->key_identifier
, lki
)) {
2698 sa_key
->rx_latest
= TRUE
;
2699 sa_key
->tx_latest
= TRUE
;
2700 latest_sak
= sa_key
;
2701 principal
->to_use_sak
= TRUE
;
2703 sa_key
->rx_latest
= FALSE
;
2704 sa_key
->tx_latest
= FALSE
;
2708 wpa_printf(MSG_ERROR
, "lki related sak not found");
2712 dl_list_for_each(rxsc
, &principal
->rxsc_list
, struct receive_sc
, list
) {
2713 rxsa
= ieee802_1x_kay_init_receive_sa(rxsc
, latest_sak
->an
, 1,
2718 secy_create_receive_sa(kay
, rxsa
);
2721 txsa
= ieee802_1x_kay_init_transmit_sa(principal
->txsc
, latest_sak
->an
,
2726 secy_create_transmit_sa(kay
, txsa
);
2735 * ieee802_1x_kay_delete_sas -
2737 int ieee802_1x_kay_delete_sas(struct ieee802_1x_kay
*kay
,
2738 struct ieee802_1x_mka_ki
*ki
)
2740 struct data_key
*sa_key
, *pre_key
;
2741 struct transmit_sa
*txsa
, *pre_txsa
;
2742 struct receive_sa
*rxsa
, *pre_rxsa
;
2743 struct receive_sc
*rxsc
;
2744 struct ieee802_1x_mka_participant
*principal
;
2746 wpa_printf(MSG_DEBUG
, "KaY: Entry into %s", __func__
);
2747 principal
= ieee802_1x_kay_get_principal_participant(kay
);
2751 /* remove the transmit sa */
2752 dl_list_for_each_safe(txsa
, pre_txsa
, &principal
->txsc
->sa_list
,
2753 struct transmit_sa
, list
) {
2754 if (is_ki_equal(&txsa
->pkey
->key_identifier
, ki
)) {
2755 secy_disable_transmit_sa(kay
, txsa
);
2756 ieee802_1x_kay_deinit_transmit_sa(txsa
);
2760 /* remove the receive sa */
2761 dl_list_for_each(rxsc
, &principal
->rxsc_list
, struct receive_sc
, list
) {
2762 dl_list_for_each_safe(rxsa
, pre_rxsa
, &rxsc
->sa_list
,
2763 struct receive_sa
, list
) {
2764 if (is_ki_equal(&rxsa
->pkey
->key_identifier
, ki
)) {
2765 secy_disable_receive_sa(kay
, rxsa
);
2766 ieee802_1x_kay_deinit_receive_sa(rxsa
);
2771 /* remove the sak */
2772 dl_list_for_each_safe(sa_key
, pre_key
, &principal
->sak_list
,
2773 struct data_key
, list
) {
2774 if (is_ki_equal(&sa_key
->key_identifier
, ki
)) {
2775 ieee802_1x_kay_deinit_data_key(sa_key
);
2778 if (principal
->new_key
== sa_key
)
2779 principal
->new_key
= NULL
;
2787 * ieee802_1x_kay_enable_tx_sas -
2789 int ieee802_1x_kay_enable_tx_sas(struct ieee802_1x_kay
*kay
,
2790 struct ieee802_1x_mka_ki
*lki
)
2792 struct ieee802_1x_mka_participant
*principal
;
2793 struct transmit_sa
*txsa
;
2795 principal
= ieee802_1x_kay_get_principal_participant(kay
);
2799 dl_list_for_each(txsa
, &principal
->txsc
->sa_list
, struct transmit_sa
,
2801 if (is_ki_equal(&txsa
->pkey
->key_identifier
, lki
)) {
2802 txsa
->in_use
= TRUE
;
2803 secy_enable_transmit_sa(kay
, txsa
);
2804 ieee802_1x_cp_set_usingtransmitas(
2805 principal
->kay
->cp
, TRUE
);
2806 ieee802_1x_cp_sm_step(principal
->kay
->cp
);
2815 * ieee802_1x_kay_enable_rx_sas -
2817 int ieee802_1x_kay_enable_rx_sas(struct ieee802_1x_kay
*kay
,
2818 struct ieee802_1x_mka_ki
*lki
)
2820 struct ieee802_1x_mka_participant
*principal
;
2821 struct receive_sa
*rxsa
;
2822 struct receive_sc
*rxsc
;
2824 principal
= ieee802_1x_kay_get_principal_participant(kay
);
2828 dl_list_for_each(rxsc
, &principal
->rxsc_list
, struct receive_sc
, list
) {
2829 dl_list_for_each(rxsa
, &rxsc
->sa_list
, struct receive_sa
, list
)
2831 if (is_ki_equal(&rxsa
->pkey
->key_identifier
, lki
)) {
2832 rxsa
->in_use
= TRUE
;
2833 secy_enable_receive_sa(kay
, rxsa
);
2834 ieee802_1x_cp_set_usingreceivesas(
2835 principal
->kay
->cp
, TRUE
);
2836 ieee802_1x_cp_sm_step(principal
->kay
->cp
);
2846 * ieee802_1x_kay_enable_new_info -
2848 int ieee802_1x_kay_enable_new_info(struct ieee802_1x_kay
*kay
)
2850 struct ieee802_1x_mka_participant
*principal
;
2852 principal
= ieee802_1x_kay_get_principal_participant(kay
);
2856 if (principal
->retry_count
< MAX_RETRY_CNT
) {
2857 ieee802_1x_participant_send_mkpdu(principal
);
2858 principal
->retry_count
++;
2866 * ieee802_1x_kay_cp_conf -
2868 int ieee802_1x_kay_cp_conf(struct ieee802_1x_kay
*kay
,
2869 struct ieee802_1x_cp_conf
*pconf
)
2871 pconf
->protect
= kay
->macsec_protect
;
2872 pconf
->replay_protect
= kay
->macsec_replay_protect
;
2873 pconf
->validate
= kay
->macsec_validate
;
2880 * ieee802_1x_kay_alloc_cp_sm -
2882 static struct ieee802_1x_cp_sm
*
2883 ieee802_1x_kay_alloc_cp_sm(struct ieee802_1x_kay
*kay
)
2885 struct ieee802_1x_cp_conf conf
;
2887 os_memset(&conf
, 0, sizeof(conf
));
2888 conf
.protect
= kay
->macsec_protect
;
2889 conf
.replay_protect
= kay
->macsec_replay_protect
;
2890 conf
.validate
= kay
->macsec_validate
;
2891 conf
.replay_window
= kay
->macsec_replay_window
;
2893 return ieee802_1x_cp_sm_init(kay
, &conf
);
2898 * ieee802_1x_kay_mkpdu_sanity_check -
2899 * sanity check specified in clause 11.11.2 of IEEE802.1X-2010
2901 static int ieee802_1x_kay_mkpdu_sanity_check(struct ieee802_1x_kay
*kay
,
2902 const u8
*buf
, size_t len
)
2904 struct ieee8023_hdr
*eth_hdr
;
2905 struct ieee802_1x_hdr
*eapol_hdr
;
2906 struct ieee802_1x_mka_hdr
*mka_hdr
;
2907 struct ieee802_1x_mka_basic_body
*body
;
2909 struct ieee802_1x_mka_participant
*participant
;
2911 u8 icv
[MAX_ICV_LEN
];
2914 eth_hdr
= (struct ieee8023_hdr
*) buf
;
2915 eapol_hdr
= (struct ieee802_1x_hdr
*) (eth_hdr
+ 1);
2916 mka_hdr
= (struct ieee802_1x_mka_hdr
*) (eapol_hdr
+ 1);
2918 /* destination address should be not individual address */
2919 if (os_memcmp(eth_hdr
->dest
, pae_group_addr
, ETH_ALEN
) != 0) {
2920 wpa_printf(MSG_MSGDUMP
,
2921 "KaY: ethernet destination address is not PAE group address");
2925 /* MKPDU should not less than 32 octets */
2926 mka_msg_len
= be_to_host16(eapol_hdr
->length
);
2927 if (mka_msg_len
< 32) {
2928 wpa_printf(MSG_MSGDUMP
, "KaY: MKPDU is less than 32 octets");
2931 /* MKPDU should multiple 4 octets */
2932 if ((mka_msg_len
% 4) != 0) {
2933 wpa_printf(MSG_MSGDUMP
,
2934 "KaY: MKPDU is not multiple of 4 octets");
2938 body
= (struct ieee802_1x_mka_basic_body
*) mka_hdr
;
2939 ieee802_1x_mka_dump_basic_body(body
);
2940 body_len
= get_mka_param_body_len(body
);
2941 /* EAPOL-MKA body should comprise basic parameter set and ICV */
2942 if (mka_msg_len
< MKA_HDR_LEN
+ body_len
+ DEFAULT_ICV_LEN
) {
2943 wpa_printf(MSG_ERROR
,
2944 "KaY: Received EAPOL-MKA Packet Body Length (%d bytes) is less than the Basic Parameter Set Header Length (%d bytes) + the Basic Parameter Set Body Length (%d bytes) + %d bytes of ICV",
2945 (int) mka_msg_len
, (int) MKA_HDR_LEN
,
2946 (int) body_len
, DEFAULT_ICV_LEN
);
2950 /* CKN should be owned by I */
2951 participant
= ieee802_1x_kay_get_participant(kay
, body
->ckn
);
2953 wpa_printf(MSG_DEBUG
, "CKN is not included in my CA");
2957 /* algorithm agility check */
2958 if (os_memcmp(body
->algo_agility
, mka_algo_agility
,
2959 sizeof(body
->algo_agility
)) != 0) {
2960 wpa_printf(MSG_ERROR
,
2961 "KaY: peer's algorithm agility not supported for me");
2967 * The ICV will comprise the final octets of the packet body, whatever
2968 * its size, not the fixed length 16 octets, indicated by the EAPOL
2969 * packet body length.
2971 if (mka_alg_tbl
[kay
->mka_algindex
].icv_hash(
2972 participant
->ick
.key
,
2973 buf
, len
- mka_alg_tbl
[kay
->mka_algindex
].icv_len
, icv
)) {
2974 wpa_printf(MSG_ERROR
, "KaY: omac1_aes_128 failed");
2977 msg_icv
= ieee802_1x_mka_decode_icv_body(participant
, (u8
*) mka_hdr
,
2981 if (os_memcmp_const(msg_icv
, icv
,
2982 mka_alg_tbl
[kay
->mka_algindex
].icv_len
) !=
2984 wpa_printf(MSG_ERROR
,
2985 "KaY: Computed ICV is not equal to Received ICV");
2989 wpa_printf(MSG_ERROR
, "KaY: No ICV");
2998 * ieee802_1x_kay_decode_mkpdu -
3000 static int ieee802_1x_kay_decode_mkpdu(struct ieee802_1x_kay
*kay
,
3001 const u8
*buf
, size_t len
)
3003 struct ieee802_1x_mka_participant
*participant
;
3004 struct ieee802_1x_mka_hdr
*hdr
;
3010 Boolean my_included
;
3011 Boolean handled
[256];
3013 if (ieee802_1x_kay_mkpdu_sanity_check(kay
, buf
, len
))
3016 /* handle basic parameter set */
3017 pos
= buf
+ sizeof(struct ieee8023_hdr
) + sizeof(struct ieee802_1x_hdr
);
3018 left_len
= len
- sizeof(struct ieee8023_hdr
) -
3019 sizeof(struct ieee802_1x_hdr
);
3020 participant
= ieee802_1x_mka_decode_basic_body(kay
, pos
, left_len
);
3024 /* to skip basic parameter set */
3025 hdr
= (struct ieee802_1x_mka_hdr
*) pos
;
3026 body_len
= get_mka_param_body_len(hdr
);
3027 pos
+= body_len
+ MKA_HDR_LEN
;
3028 left_len
-= body_len
+ MKA_HDR_LEN
;
3030 /* check i am in the peer's peer list */
3031 my_included
= ieee802_1x_mka_i_in_peerlist(participant
, pos
, left_len
);
3033 /* accept the peer as live peer */
3034 if (!ieee802_1x_kay_is_in_peer(
3036 participant
->current_peer_id
.mi
)) {
3037 if (!ieee802_1x_kay_create_live_peer(
3039 participant
->current_peer_id
.mi
,
3041 participant
->current_peer_id
.mn
)))
3043 ieee802_1x_kay_elect_key_server(participant
);
3044 ieee802_1x_kay_decide_macsec_use(participant
);
3046 if (ieee802_1x_kay_is_in_potential_peer(
3047 participant
, participant
->current_peer_id
.mi
)) {
3048 if (!ieee802_1x_kay_move_live_peer(
3050 participant
->current_peer_id
.mi
,
3051 be_to_host32(participant
->
3052 current_peer_id
.mn
)))
3054 ieee802_1x_kay_elect_key_server(participant
);
3055 ieee802_1x_kay_decide_macsec_use(participant
);
3060 * Handle other parameter set than basic parameter set.
3061 * Each parameter set should be present only once.
3063 for (i
= 0; i
< 256; i
++)
3067 while (left_len
> MKA_HDR_LEN
+ DEFAULT_ICV_LEN
) {
3068 hdr
= (struct ieee802_1x_mka_hdr
*) pos
;
3069 body_len
= get_mka_param_body_len(hdr
);
3070 body_type
= get_mka_param_body_type(hdr
);
3072 if (body_type
== MKA_ICV_INDICATOR
)
3075 if (left_len
< (MKA_HDR_LEN
+ body_len
+ DEFAULT_ICV_LEN
)) {
3076 wpa_printf(MSG_ERROR
,
3077 "KaY: MKA Peer Packet Body Length (%d bytes) is less than the Parameter Set Header Length (%d bytes) + the Parameter Set Body Length (%d bytes) + %d bytes of ICV",
3078 (int) left_len
, (int) MKA_HDR_LEN
,
3079 (int) body_len
, DEFAULT_ICV_LEN
);
3083 if (handled
[body_type
])
3086 handled
[body_type
] = TRUE
;
3087 if (body_type
< ARRAY_SIZE(mka_body_handler
) &&
3088 mka_body_handler
[body_type
].body_rx
) {
3089 mka_body_handler
[body_type
].body_rx
3090 (participant
, pos
, left_len
);
3092 wpa_printf(MSG_ERROR
,
3093 "The type %d not supported in this MKA version %d",
3094 body_type
, MKA_VERSION_ID
);
3098 pos
+= body_len
+ MKA_HDR_LEN
;
3099 left_len
-= body_len
+ MKA_HDR_LEN
;
3103 participant
->retry_count
= 0;
3104 participant
->active
= TRUE
;
3111 static void kay_l2_receive(void *ctx
, const u8
*src_addr
, const u8
*buf
,
3114 struct ieee802_1x_kay
*kay
= ctx
;
3115 struct ieee8023_hdr
*eth_hdr
;
3116 struct ieee802_1x_hdr
*eapol_hdr
;
3118 /* must contain at least ieee8023_hdr + ieee802_1x_hdr */
3119 if (len
< sizeof(*eth_hdr
) + sizeof(*eapol_hdr
)) {
3120 wpa_printf(MSG_MSGDUMP
, "KaY: EAPOL frame too short (%lu)",
3121 (unsigned long) len
);
3125 eth_hdr
= (struct ieee8023_hdr
*) buf
;
3126 eapol_hdr
= (struct ieee802_1x_hdr
*) (eth_hdr
+ 1);
3127 if (len
!= sizeof(*eth_hdr
) + sizeof(*eapol_hdr
) +
3128 be_to_host16(eapol_hdr
->length
)) {
3129 wpa_printf(MSG_MSGDUMP
, "KAY: EAPOL MPDU is invalid: (%lu-%lu)",
3130 (unsigned long) len
,
3131 (unsigned long) be_to_host16(eapol_hdr
->length
));
3135 if (eapol_hdr
->version
< EAPOL_VERSION
) {
3136 wpa_printf(MSG_MSGDUMP
, "KaY: version %d does not support MKA",
3137 eapol_hdr
->version
);
3140 if (be_to_host16(eth_hdr
->ethertype
) != ETH_P_PAE
||
3141 eapol_hdr
->type
!= IEEE802_1X_TYPE_EAPOL_MKA
)
3144 wpa_hexdump(MSG_DEBUG
, "RX EAPOL-MKA: ", buf
, len
);
3145 if (dl_list_empty(&kay
->participant_list
)) {
3146 wpa_printf(MSG_ERROR
, "KaY: no MKA participant instance");
3150 ieee802_1x_kay_decode_mkpdu(kay
, buf
, len
);
3155 * ieee802_1x_kay_init -
3157 struct ieee802_1x_kay
*
3158 ieee802_1x_kay_init(struct ieee802_1x_kay_ctx
*ctx
, enum macsec_policy policy
,
3159 const char *ifname
, const u8
*addr
)
3161 struct ieee802_1x_kay
*kay
;
3163 kay
= os_zalloc(sizeof(*kay
));
3165 wpa_printf(MSG_ERROR
, "KaY-%s: out of memory", __func__
);
3172 kay
->active
= FALSE
;
3174 kay
->authenticated
= FALSE
;
3175 kay
->secured
= FALSE
;
3176 kay
->failed
= FALSE
;
3177 kay
->policy
= policy
;
3179 os_strlcpy(kay
->if_name
, ifname
, IFNAMSIZ
);
3180 os_memcpy(kay
->actor_sci
.addr
, addr
, ETH_ALEN
);
3181 kay
->actor_sci
.port
= host_to_be16(0x0001);
3182 kay
->actor_priority
= DEFAULT_PRIO_NOT_KEY_SERVER
;
3184 /* While actor acts as a key server, shall distribute sakey */
3189 kay
->pn_exhaustion
= PENDING_PN_EXHAUSTION
;
3190 kay
->macsec_csindex
= DEFAULT_CS_INDEX
;
3191 kay
->mka_algindex
= DEFAULT_MKA_ALG_INDEX
;
3192 kay
->mka_version
= MKA_VERSION_ID
;
3194 os_memcpy(kay
->algo_agility
, mka_algo_agility
,
3195 sizeof(kay
->algo_agility
));
3197 dl_list_init(&kay
->participant_list
);
3199 if (policy
== DO_NOT_SECURE
) {
3200 kay
->macsec_capable
= MACSEC_CAP_NOT_IMPLEMENTED
;
3201 kay
->macsec_desired
= FALSE
;
3202 kay
->macsec_protect
= FALSE
;
3203 kay
->macsec_validate
= Disabled
;
3204 kay
->macsec_replay_protect
= FALSE
;
3205 kay
->macsec_replay_window
= 0;
3206 kay
->macsec_confidentiality
= CONFIDENTIALITY_NONE
;
3208 kay
->macsec_capable
= MACSEC_CAP_INTEG_AND_CONF_0_30_50
;
3209 kay
->macsec_desired
= TRUE
;
3210 kay
->macsec_protect
= TRUE
;
3211 kay
->macsec_validate
= Strict
;
3212 kay
->macsec_replay_protect
= FALSE
;
3213 kay
->macsec_replay_window
= 0;
3214 kay
->macsec_confidentiality
= CONFIDENTIALITY_OFFSET_0
;
3217 wpa_printf(MSG_DEBUG
, "KaY: state machine created");
3219 /* Initialize the SecY must be prio to CP, as CP will control SecY */
3220 secy_init_macsec(kay
);
3221 secy_get_available_transmit_sc(kay
, &kay
->sc_ch
);
3223 wpa_printf(MSG_DEBUG
, "KaY: secy init macsec done");
3226 kay
->cp
= ieee802_1x_kay_alloc_cp_sm(kay
);
3227 if (kay
->cp
== NULL
) {
3228 ieee802_1x_kay_deinit(kay
);
3232 if (policy
== DO_NOT_SECURE
) {
3233 ieee802_1x_cp_connect_authenticated(kay
->cp
);
3234 ieee802_1x_cp_sm_step(kay
->cp
);
3236 kay
->l2_mka
= l2_packet_init(kay
->if_name
, NULL
, ETH_P_PAE
,
3237 kay_l2_receive
, kay
, 1);
3238 if (kay
->l2_mka
== NULL
) {
3239 wpa_printf(MSG_WARNING
,
3240 "KaY: Failed to initialize L2 packet processing for MKA packet");
3241 ieee802_1x_kay_deinit(kay
);
3251 * ieee802_1x_kay_deinit -
3254 ieee802_1x_kay_deinit(struct ieee802_1x_kay
*kay
)
3256 struct ieee802_1x_mka_participant
*participant
;
3261 wpa_printf(MSG_DEBUG
, "KaY: state machine removed");
3263 while (!dl_list_empty(&kay
->participant_list
)) {
3264 participant
= dl_list_entry(kay
->participant_list
.next
,
3265 struct ieee802_1x_mka_participant
,
3267 ieee802_1x_kay_delete_mka(kay
, &participant
->ckn
);
3270 ieee802_1x_cp_sm_deinit(kay
->cp
);
3271 secy_deinit_macsec(kay
);
3274 l2_packet_deinit(kay
->l2_mka
);
3284 * ieee802_1x_kay_create_mka -
3286 struct ieee802_1x_mka_participant
*
3287 ieee802_1x_kay_create_mka(struct ieee802_1x_kay
*kay
, struct mka_key_name
*ckn
,
3288 struct mka_key
*cak
, u32 life
,
3289 enum mka_created_mode mode
, Boolean is_authenticator
)
3291 struct ieee802_1x_mka_participant
*participant
;
3294 if (!kay
|| !ckn
|| !cak
) {
3295 wpa_printf(MSG_ERROR
, "KaY: ckn or cak is null");
3299 if (cak
->len
!= mka_alg_tbl
[kay
->mka_algindex
].cak_len
) {
3300 wpa_printf(MSG_ERROR
, "KaY: CAK length not follow key schema");
3303 if (ckn
->len
> MAX_CKN_LEN
) {
3304 wpa_printf(MSG_ERROR
, "KaY: CKN is out of range(<=32 bytes)");
3308 wpa_printf(MSG_ERROR
, "KaY: Now is at disable state");
3312 participant
= os_zalloc(sizeof(*participant
));
3314 wpa_printf(MSG_ERROR
, "KaY-%s: out of memory", __func__
);
3318 participant
->ckn
.len
= ckn
->len
;
3319 os_memcpy(participant
->ckn
.name
, ckn
->name
, ckn
->len
);
3320 participant
->cak
.len
= cak
->len
;
3321 os_memcpy(participant
->cak
.key
, cak
->key
, cak
->len
);
3323 participant
->cak_life
= life
+ time(NULL
);
3327 if (is_authenticator
) {
3328 participant
->is_obliged_key_server
= TRUE
;
3329 participant
->can_be_key_server
= TRUE
;
3330 participant
->is_key_server
= TRUE
;
3331 participant
->principal
= TRUE
;
3333 os_memcpy(&kay
->key_server_sci
, &kay
->actor_sci
,
3334 sizeof(kay
->key_server_sci
));
3335 kay
->key_server_priority
= kay
->actor_priority
;
3336 participant
->is_elected
= TRUE
;
3338 participant
->is_obliged_key_server
= FALSE
;
3339 participant
->can_be_key_server
= FALSE
;
3340 participant
->is_key_server
= FALSE
;
3341 participant
->is_elected
= TRUE
;
3346 participant
->is_obliged_key_server
= FALSE
;
3347 participant
->can_be_key_server
= TRUE
;
3348 participant
->is_key_server
= TRUE
;
3349 participant
->is_elected
= FALSE
;
3353 participant
->cached
= FALSE
;
3355 participant
->active
= FALSE
;
3356 participant
->participant
= FALSE
;
3357 participant
->retain
= FALSE
;
3358 participant
->activate
= DEFAULT
;
3360 if (participant
->is_key_server
)
3361 participant
->principal
= TRUE
;
3363 dl_list_init(&participant
->live_peers
);
3364 dl_list_init(&participant
->potential_peers
);
3366 participant
->retry_count
= 0;
3367 participant
->kay
= kay
;
3369 if (os_get_random(participant
->mi
, sizeof(participant
->mi
)) < 0)
3371 participant
->mn
= 0;
3373 participant
->lrx
= FALSE
;
3374 participant
->ltx
= FALSE
;
3375 participant
->orx
= FALSE
;
3376 participant
->otx
= FALSE
;
3377 participant
->to_dist_sak
= FALSE
;
3378 participant
->to_use_sak
= FALSE
;
3379 participant
->new_sak
= FALSE
;
3380 dl_list_init(&participant
->sak_list
);
3381 participant
->new_key
= NULL
;
3382 dl_list_init(&participant
->rxsc_list
);
3383 participant
->txsc
= ieee802_1x_kay_init_transmit_sc(&kay
->actor_sci
,
3385 secy_cp_control_protect_frames(kay
, kay
->macsec_protect
);
3386 secy_cp_control_replay(kay
, kay
->macsec_replay_protect
,
3387 kay
->macsec_replay_window
);
3388 secy_create_transmit_sc(kay
, participant
->txsc
);
3390 /* to derive KEK from CAK and CKN */
3391 participant
->kek
.len
= mka_alg_tbl
[kay
->mka_algindex
].kek_len
;
3392 if (mka_alg_tbl
[kay
->mka_algindex
].kek_trfm(participant
->cak
.key
,
3393 participant
->ckn
.name
,
3394 participant
->ckn
.len
,
3395 participant
->kek
.key
)) {
3396 wpa_printf(MSG_ERROR
, "KaY: Derived KEK failed");
3399 wpa_hexdump_key(MSG_DEBUG
, "KaY: Derived KEK",
3400 participant
->kek
.key
, participant
->kek
.len
);
3402 /* to derive ICK from CAK and CKN */
3403 participant
->ick
.len
= mka_alg_tbl
[kay
->mka_algindex
].ick_len
;
3404 if (mka_alg_tbl
[kay
->mka_algindex
].ick_trfm(participant
->cak
.key
,
3405 participant
->ckn
.name
,
3406 participant
->ckn
.len
,
3407 participant
->ick
.key
)) {
3408 wpa_printf(MSG_ERROR
, "KaY: Derived ICK failed");
3411 wpa_hexdump_key(MSG_DEBUG
, "KaY: Derived ICK",
3412 participant
->ick
.key
, participant
->ick
.len
);
3414 dl_list_add(&kay
->participant_list
, &participant
->list
);
3415 wpa_hexdump(MSG_DEBUG
, "KaY: Participant created:",
3416 ckn
->name
, ckn
->len
);
3418 usecs
= os_random() % (MKA_HELLO_TIME
* 1000);
3419 eloop_register_timeout(0, usecs
, ieee802_1x_participant_timer
,
3421 participant
->mka_life
= MKA_LIFE_TIME
/ 1000 + time(NULL
) +
3427 os_free(participant
);
3433 * ieee802_1x_kay_delete_mka -
3436 ieee802_1x_kay_delete_mka(struct ieee802_1x_kay
*kay
, struct mka_key_name
*ckn
)
3438 struct ieee802_1x_mka_participant
*participant
;
3439 struct ieee802_1x_kay_peer
*peer
;
3440 struct data_key
*sak
;
3441 struct receive_sc
*rxsc
;
3446 wpa_printf(MSG_DEBUG
, "KaY: participant removed");
3448 /* get the participant */
3449 participant
= ieee802_1x_kay_get_participant(kay
, ckn
->name
);
3451 wpa_hexdump(MSG_DEBUG
, "KaY: participant is not found",
3452 ckn
->name
, ckn
->len
);
3456 eloop_cancel_timeout(ieee802_1x_participant_timer
, participant
, NULL
);
3457 dl_list_del(&participant
->list
);
3459 /* remove live peer */
3460 while (!dl_list_empty(&participant
->live_peers
)) {
3461 peer
= dl_list_entry(participant
->live_peers
.next
,
3462 struct ieee802_1x_kay_peer
, list
);
3463 dl_list_del(&peer
->list
);
3467 /* remove potential peer */
3468 while (!dl_list_empty(&participant
->potential_peers
)) {
3469 peer
= dl_list_entry(participant
->potential_peers
.next
,
3470 struct ieee802_1x_kay_peer
, list
);
3471 dl_list_del(&peer
->list
);
3476 while (!dl_list_empty(&participant
->sak_list
)) {
3477 sak
= dl_list_entry(participant
->sak_list
.next
,
3478 struct data_key
, list
);
3479 dl_list_del(&sak
->list
);
3483 while (!dl_list_empty(&participant
->rxsc_list
)) {
3484 rxsc
= dl_list_entry(participant
->rxsc_list
.next
,
3485 struct receive_sc
, list
);
3486 secy_delete_receive_sc(kay
, rxsc
);
3487 ieee802_1x_kay_deinit_receive_sc(participant
, rxsc
);
3489 secy_delete_transmit_sc(kay
, participant
->txsc
);
3490 ieee802_1x_kay_deinit_transmit_sc(participant
, participant
->txsc
);
3492 os_memset(&participant
->cak
, 0, sizeof(participant
->cak
));
3493 os_memset(&participant
->kek
, 0, sizeof(participant
->kek
));
3494 os_memset(&participant
->ick
, 0, sizeof(participant
->ick
));
3495 os_free(participant
);
3500 * ieee802_1x_kay_mka_participate -
3502 void ieee802_1x_kay_mka_participate(struct ieee802_1x_kay
*kay
,
3503 struct mka_key_name
*ckn
,
3506 struct ieee802_1x_mka_participant
*participant
;
3511 participant
= ieee802_1x_kay_get_participant(kay
, ckn
->name
);
3515 participant
->active
= status
;
3520 * ieee802_1x_kay_new_sak -
3523 ieee802_1x_kay_new_sak(struct ieee802_1x_kay
*kay
)
3525 struct ieee802_1x_mka_participant
*participant
;
3530 participant
= ieee802_1x_kay_get_principal_participant(kay
);
3534 participant
->new_sak
= TRUE
;
3535 wpa_printf(MSG_DEBUG
, "KaY: new SAK signal");
3542 * ieee802_1x_kay_change_cipher_suite -
3545 ieee802_1x_kay_change_cipher_suite(struct ieee802_1x_kay
*kay
, int cs_index
)
3547 struct ieee802_1x_mka_participant
*participant
;
3552 if ((unsigned int) cs_index
>= CS_TABLE_SIZE
) {
3553 wpa_printf(MSG_ERROR
,
3554 "KaY: Configured cipher suite index is out of range");
3557 if (kay
->macsec_csindex
== cs_index
)
3561 kay
->macsec_desired
= FALSE
;
3563 kay
->macsec_csindex
= cs_index
;
3564 kay
->macsec_capable
= cipher_suite_tbl
[kay
->macsec_csindex
].capable
;
3566 participant
= ieee802_1x_kay_get_principal_participant(kay
);
3568 wpa_printf(MSG_INFO
, "KaY: Cipher Suite changed");
3569 participant
->new_sak
= TRUE
;