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 #define MKA_ALIGN_LENGTH(len) (((len) + 0x3) & ~0x3)
34 /* IEEE Std 802.1X-2010, Table 9-1 - MKA Algorithm Agility */
35 #define MKA_ALGO_AGILITY_2009 { 0x00, 0x80, 0xC2, 0x01 }
36 static u8 mka_algo_agility
[4] = MKA_ALGO_AGILITY_2009
;
38 /* IEEE802.1AE-2006 Table 14-1 MACsec Cipher Suites */
39 static struct macsec_ciphersuite cipher_suite_tbl
[] = {
42 .id
= CS_ID_GCM_AES_128
,
43 .name
= CS_NAME_GCM_AES_128
,
44 .capable
= MACSEC_CAP_INTEG_AND_CONF_0_30_50
,
45 .sak_len
= DEFAULT_SA_KEY_LEN
,
49 #define CS_TABLE_SIZE (ARRAY_SIZE(cipher_suite_tbl))
50 #define DEFAULT_CS_INDEX 0
52 static struct mka_alg mka_alg_tbl
[] = {
54 .parameter
= MKA_ALGO_AGILITY_2009
,
56 /* 128-bit CAK, KEK, ICK, ICV */
57 .cak_len
= DEFAULT_ICV_LEN
,
58 .kek_len
= DEFAULT_ICV_LEN
,
59 .ick_len
= DEFAULT_ICV_LEN
,
60 .icv_len
= DEFAULT_ICV_LEN
,
62 .cak_trfm
= ieee802_1x_cak_128bits_aes_cmac
,
63 .ckn_trfm
= ieee802_1x_ckn_128bits_aes_cmac
,
64 .kek_trfm
= ieee802_1x_kek_128bits_aes_cmac
,
65 .ick_trfm
= ieee802_1x_ick_128bits_aes_cmac
,
66 .icv_hash
= ieee802_1x_icv_128bits_aes_cmac
,
71 #define MKA_ALG_TABLE_SIZE (ARRAY_SIZE(mka_alg_tbl))
74 static int is_ki_equal(struct ieee802_1x_mka_ki
*ki1
,
75 struct ieee802_1x_mka_ki
*ki2
)
77 return os_memcmp(ki1
->mi
, ki2
->mi
, MI_LEN
) == 0 &&
82 struct mka_param_body_handler
{
83 int (*body_tx
)(struct ieee802_1x_mka_participant
*participant
,
85 int (*body_rx
)(struct ieee802_1x_mka_participant
*participant
,
86 const u8
*mka_msg
, size_t msg_len
);
87 int (*body_length
)(struct ieee802_1x_mka_participant
*participant
);
88 Boolean (*body_present
)(struct ieee802_1x_mka_participant
*participant
);
92 static void set_mka_param_body_len(void *body
, unsigned int len
)
94 struct ieee802_1x_mka_hdr
*hdr
= body
;
95 hdr
->length
= (len
>> 8) & 0x0f;
96 hdr
->length1
= len
& 0xff;
100 static unsigned int get_mka_param_body_len(const void *body
)
102 const struct ieee802_1x_mka_hdr
*hdr
= body
;
103 return (hdr
->length
<< 8) | hdr
->length1
;
107 static u8
get_mka_param_body_type(const void *body
)
109 const struct ieee802_1x_mka_hdr
*hdr
= body
;
115 * ieee802_1x_mka_dump_basic_body -
118 ieee802_1x_mka_dump_basic_body(struct ieee802_1x_mka_basic_body
*body
)
125 body_len
= get_mka_param_body_len(body
);
126 wpa_printf(MSG_DEBUG
, "*** MKA Basic Parameter set ***");
127 wpa_printf(MSG_DEBUG
, "\tVersion.......: %d", body
->version
);
128 wpa_printf(MSG_DEBUG
, "\tPriority......: %d", body
->priority
);
129 wpa_printf(MSG_DEBUG
, "\tKeySvr........: %d", body
->key_server
);
130 wpa_printf(MSG_DEBUG
, "\tMACSecDesired.: %d", body
->macsec_desired
);
131 wpa_printf(MSG_DEBUG
, "\tMACSecCapable.: %d", body
->macsec_capability
);
132 wpa_printf(MSG_DEBUG
, "\tBody Length...: %zu", body_len
);
133 wpa_printf(MSG_DEBUG
, "\tSCI MAC.......: " MACSTR
,
134 MAC2STR(body
->actor_sci
.addr
));
135 wpa_printf(MSG_DEBUG
, "\tSCI Port .....: %d",
136 be_to_host16(body
->actor_sci
.port
));
137 wpa_hexdump(MSG_DEBUG
, "\tMember Id.....:",
138 body
->actor_mi
, sizeof(body
->actor_mi
));
139 wpa_printf(MSG_DEBUG
, "\tMessage Number: %d",
140 be_to_host32(body
->actor_mn
));
141 wpa_hexdump(MSG_DEBUG
, "\tAlgo Agility..:",
142 body
->algo_agility
, sizeof(body
->algo_agility
));
143 wpa_hexdump_ascii(MSG_DEBUG
, "\tCAK Name......:", body
->ckn
,
144 body_len
+ MKA_HDR_LEN
- sizeof(*body
));
149 * ieee802_1x_mka_dump_peer_body -
152 ieee802_1x_mka_dump_peer_body(struct ieee802_1x_mka_peer_body
*body
)
162 body_len
= get_mka_param_body_len(body
);
163 if (body
->type
== MKA_LIVE_PEER_LIST
) {
164 wpa_printf(MSG_DEBUG
, "*** Live Peer List ***");
165 wpa_printf(MSG_DEBUG
, "\tBody Length...: %zu", body_len
);
166 } else if (body
->type
== MKA_POTENTIAL_PEER_LIST
) {
167 wpa_printf(MSG_DEBUG
, "*** Potential Live Peer List ***");
168 wpa_printf(MSG_DEBUG
, "\tBody Length...: %zu", body_len
);
171 for (i
= 0; i
< body_len
; i
+= MI_LEN
+ sizeof(mn
)) {
173 os_memcpy(&mn
, mi
+ MI_LEN
, sizeof(mn
));
174 wpa_hexdump_ascii(MSG_DEBUG
, "\tMember Id.....:", mi
, MI_LEN
);
175 wpa_printf(MSG_DEBUG
, "\tMessage Number: %d", be_to_host32(mn
));
181 * ieee802_1x_mka_dump_dist_sak_body -
184 ieee802_1x_mka_dump_dist_sak_body(struct ieee802_1x_mka_dist_sak_body
*body
)
191 body_len
= get_mka_param_body_len(body
);
192 wpa_printf(MSG_INFO
, "*** Distributed SAK ***");
193 wpa_printf(MSG_INFO
, "\tDistributed AN........: %d", body
->dan
);
194 wpa_printf(MSG_INFO
, "\tConfidentiality Offset: %d",
195 body
->confid_offset
);
196 wpa_printf(MSG_INFO
, "\tBody Length...........: %zu", body_len
);
200 wpa_printf(MSG_INFO
, "\tKey Number............: %d",
201 be_to_host32(body
->kn
));
202 wpa_hexdump(MSG_INFO
, "\tAES Key Wrap of SAK...:", body
->sak
, 24);
206 static const char * yes_no(int val
)
208 return val
? "Yes" : "No";
213 * ieee802_1x_mka_dump_sak_use_body -
216 ieee802_1x_mka_dump_sak_use_body(struct ieee802_1x_mka_sak_use_body
*body
)
223 body_len
= get_mka_param_body_len(body
);
224 wpa_printf(MSG_DEBUG
, "*** MACsec SAK Use ***");
225 wpa_printf(MSG_DEBUG
, "\tLatest Key AN....: %d", body
->lan
);
226 wpa_printf(MSG_DEBUG
, "\tLatest Key Tx....: %s", yes_no(body
->ltx
));
227 wpa_printf(MSG_DEBUG
, "\tLatest Key Rx....: %s", yes_no(body
->lrx
));
228 wpa_printf(MSG_DEBUG
, "\tOld Key AN....: %d", body
->oan
);
229 wpa_printf(MSG_DEBUG
, "\tOld Key Tx....: %s", yes_no(body
->otx
));
230 wpa_printf(MSG_DEBUG
, "\tOld Key Rx....: %s", yes_no(body
->orx
));
231 wpa_printf(MSG_DEBUG
, "\tPlain Key Tx....: %s", yes_no(body
->ptx
));
232 wpa_printf(MSG_DEBUG
, "\tPlain Key Rx....: %s", yes_no(body
->prx
));
233 wpa_printf(MSG_DEBUG
, "\tDelay Protect....: %s",
234 yes_no(body
->delay_protect
));
235 wpa_printf(MSG_DEBUG
, "\tBody Length......: %d", body_len
);
239 wpa_hexdump(MSG_DEBUG
, "\tKey Server MI....:",
240 body
->lsrv_mi
, sizeof(body
->lsrv_mi
));
241 wpa_printf(MSG_DEBUG
, "\tKey Number.......: %u",
242 be_to_host32(body
->lkn
));
243 wpa_printf(MSG_DEBUG
, "\tLowest PN........: %u",
244 be_to_host32(body
->llpn
));
245 wpa_hexdump_ascii(MSG_DEBUG
, "\tOld Key Server MI....:",
246 body
->osrv_mi
, sizeof(body
->osrv_mi
));
247 wpa_printf(MSG_DEBUG
, "\tOld Key Number.......: %u",
248 be_to_host32(body
->okn
));
249 wpa_printf(MSG_DEBUG
, "\tOld Lowest PN........: %u",
250 be_to_host32(body
->olpn
));
255 * ieee802_1x_kay_get_participant -
257 static struct ieee802_1x_mka_participant
*
258 ieee802_1x_kay_get_participant(struct ieee802_1x_kay
*kay
, const u8
*ckn
)
260 struct ieee802_1x_mka_participant
*participant
;
262 dl_list_for_each(participant
, &kay
->participant_list
,
263 struct ieee802_1x_mka_participant
, list
) {
264 if (os_memcmp(participant
->ckn
.name
, ckn
,
265 participant
->ckn
.len
) == 0)
269 wpa_printf(MSG_DEBUG
, "KaY: participant is not found");
276 * ieee802_1x_kay_get_principal_participant -
278 static struct ieee802_1x_mka_participant
*
279 ieee802_1x_kay_get_principal_participant(struct ieee802_1x_kay
*kay
)
281 struct ieee802_1x_mka_participant
*participant
;
283 dl_list_for_each(participant
, &kay
->participant_list
,
284 struct ieee802_1x_mka_participant
, list
) {
285 if (participant
->principal
)
289 wpa_printf(MSG_DEBUG
, "KaY: principal participant is not founded");
294 static struct ieee802_1x_kay_peer
* get_peer_mi(struct dl_list
*peers
,
297 struct ieee802_1x_kay_peer
*peer
;
299 dl_list_for_each(peer
, peers
, struct ieee802_1x_kay_peer
, list
) {
300 if (os_memcmp(peer
->mi
, mi
, MI_LEN
) == 0)
309 * ieee802_1x_kay_get_potential_peer
311 static struct ieee802_1x_kay_peer
*
312 ieee802_1x_kay_get_potential_peer(
313 struct ieee802_1x_mka_participant
*participant
, const u8
*mi
)
315 return get_peer_mi(&participant
->potential_peers
, mi
);
320 * ieee802_1x_kay_get_live_peer
322 static struct ieee802_1x_kay_peer
*
323 ieee802_1x_kay_get_live_peer(struct ieee802_1x_mka_participant
*participant
,
326 return get_peer_mi(&participant
->live_peers
, mi
);
331 * ieee802_1x_kay_is_in_potential_peer
334 ieee802_1x_kay_is_in_potential_peer(
335 struct ieee802_1x_mka_participant
*participant
, const u8
*mi
)
337 return ieee802_1x_kay_get_potential_peer(participant
, mi
) != NULL
;
342 * ieee802_1x_kay_is_in_live_peer
345 ieee802_1x_kay_is_in_live_peer(
346 struct ieee802_1x_mka_participant
*participant
, const u8
*mi
)
348 return ieee802_1x_kay_get_live_peer(participant
, mi
) != NULL
;
353 * ieee802_1x_kay_is_in_peer
356 ieee802_1x_kay_is_in_peer(struct ieee802_1x_mka_participant
*participant
,
359 return ieee802_1x_kay_is_in_live_peer(participant
, mi
) ||
360 ieee802_1x_kay_is_in_potential_peer(participant
, mi
);
365 * ieee802_1x_kay_get_peer
367 static struct ieee802_1x_kay_peer
*
368 ieee802_1x_kay_get_peer(struct ieee802_1x_mka_participant
*participant
,
371 struct ieee802_1x_kay_peer
*peer
;
373 peer
= ieee802_1x_kay_get_live_peer(participant
, mi
);
377 return ieee802_1x_kay_get_potential_peer(participant
, mi
);
382 * ieee802_1x_kay_get_cipher_suite
384 static struct macsec_ciphersuite
*
385 ieee802_1x_kay_get_cipher_suite(struct ieee802_1x_mka_participant
*participant
,
390 for (i
= 0; i
< CS_TABLE_SIZE
; i
++) {
391 if (os_memcmp(cipher_suite_tbl
[i
].id
, cs_id
, CS_ID_LEN
) == 0)
392 return &cipher_suite_tbl
[i
];
399 static Boolean
sci_equal(const struct ieee802_1x_mka_sci
*a
,
400 const struct ieee802_1x_mka_sci
*b
)
402 return os_memcmp(a
, b
, sizeof(struct ieee802_1x_mka_sci
)) == 0;
407 * ieee802_1x_kay_get_peer_sci
409 static struct ieee802_1x_kay_peer
*
410 ieee802_1x_kay_get_peer_sci(struct ieee802_1x_mka_participant
*participant
,
411 const struct ieee802_1x_mka_sci
*sci
)
413 struct ieee802_1x_kay_peer
*peer
;
415 dl_list_for_each(peer
, &participant
->live_peers
,
416 struct ieee802_1x_kay_peer
, list
) {
417 if (sci_equal(&peer
->sci
, sci
))
421 dl_list_for_each(peer
, &participant
->potential_peers
,
422 struct ieee802_1x_kay_peer
, list
) {
423 if (sci_equal(&peer
->sci
, sci
))
432 * ieee802_1x_kay_init_receive_sa -
434 static struct receive_sa
*
435 ieee802_1x_kay_init_receive_sa(struct receive_sc
*psc
, u8 an
, u32 lowest_pn
,
436 struct data_key
*key
)
438 struct receive_sa
*psa
;
443 psa
= os_zalloc(sizeof(*psa
));
445 wpa_printf(MSG_ERROR
, "%s: out of memory", __func__
);
450 psa
->lowest_pn
= lowest_pn
;
451 psa
->next_pn
= lowest_pn
;
455 os_get_time(&psa
->created_time
);
458 dl_list_add(&psc
->sa_list
, &psa
->list
);
459 wpa_printf(MSG_DEBUG
,
460 "KaY: Create receive SA(AN: %hhu lowest_pn: %u of SC(channel: %d)",
461 an
, lowest_pn
, psc
->channel
);
468 * ieee802_1x_kay_deinit_receive_sa -
470 static void ieee802_1x_kay_deinit_receive_sa(struct receive_sa
*psa
)
473 wpa_printf(MSG_DEBUG
,
474 "KaY: Delete receive SA(an: %hhu) of SC",
476 dl_list_del(&psa
->list
);
482 * ieee802_1x_kay_init_receive_sc -
484 static struct receive_sc
*
485 ieee802_1x_kay_init_receive_sc(const struct ieee802_1x_mka_sci
*psci
,
488 struct receive_sc
*psc
;
493 psc
= os_zalloc(sizeof(*psc
));
495 wpa_printf(MSG_ERROR
, "%s: out of memory", __func__
);
499 os_memcpy(&psc
->sci
, psci
, sizeof(psc
->sci
));
500 psc
->channel
= channel
;
502 os_get_time(&psc
->created_time
);
503 psc
->receiving
= FALSE
;
505 dl_list_init(&psc
->sa_list
);
506 wpa_printf(MSG_DEBUG
, "KaY: Create receive SC(channel: %d)", channel
);
507 wpa_hexdump(MSG_DEBUG
, "SCI: ", (u8
*)psci
, sizeof(*psci
));
514 * ieee802_1x_kay_deinit_receive_sc -
517 ieee802_1x_kay_deinit_receive_sc(
518 struct ieee802_1x_mka_participant
*participant
, struct receive_sc
*psc
)
520 struct receive_sa
*psa
, *pre_sa
;
522 wpa_printf(MSG_DEBUG
, "KaY: Delete receive SC(channel: %d)",
524 dl_list_for_each_safe(psa
, pre_sa
, &psc
->sa_list
, struct receive_sa
,
526 secy_disable_receive_sa(participant
->kay
, psa
);
527 ieee802_1x_kay_deinit_receive_sa(psa
);
529 dl_list_del(&psc
->list
);
534 static void ieee802_1x_kay_dump_peer(struct ieee802_1x_kay_peer
*peer
)
536 wpa_hexdump(MSG_DEBUG
, "\tMI: ", peer
->mi
, sizeof(peer
->mi
));
537 wpa_printf(MSG_DEBUG
, "\tMN: %d", peer
->mn
);
538 wpa_hexdump(MSG_DEBUG
, "\tSCI Addr: ", peer
->sci
.addr
, ETH_ALEN
);
539 wpa_printf(MSG_DEBUG
, "\tPort: %d", peer
->sci
.port
);
543 static struct ieee802_1x_kay_peer
*
544 ieee802_1x_kay_create_peer(const u8
*mi
, u32 mn
)
546 struct ieee802_1x_kay_peer
*peer
;
548 peer
= os_zalloc(sizeof(*peer
));
550 wpa_printf(MSG_ERROR
, "KaY-%s: out of memory", __func__
);
554 os_memcpy(peer
->mi
, mi
, MI_LEN
);
556 peer
->expire
= time(NULL
) + MKA_LIFE_TIME
/ 1000;
557 peer
->sak_used
= FALSE
;
564 * ieee802_1x_kay_create_live_peer
566 static struct ieee802_1x_kay_peer
*
567 ieee802_1x_kay_create_live_peer(struct ieee802_1x_mka_participant
*participant
,
568 const u8
*mi
, u32 mn
)
570 struct ieee802_1x_kay_peer
*peer
;
571 struct receive_sc
*rxsc
;
574 peer
= ieee802_1x_kay_create_peer(mi
, mn
);
578 os_memcpy(&peer
->sci
, &participant
->current_peer_sci
,
581 secy_get_available_receive_sc(participant
->kay
, &sc_ch
);
583 rxsc
= ieee802_1x_kay_init_receive_sc(&peer
->sci
, sc_ch
);
589 dl_list_add(&participant
->live_peers
, &peer
->list
);
590 dl_list_add(&participant
->rxsc_list
, &rxsc
->list
);
591 secy_create_receive_sc(participant
->kay
, rxsc
);
593 wpa_printf(MSG_DEBUG
, "KaY: Live peer created");
594 ieee802_1x_kay_dump_peer(peer
);
601 * ieee802_1x_kay_create_potential_peer
603 static struct ieee802_1x_kay_peer
*
604 ieee802_1x_kay_create_potential_peer(
605 struct ieee802_1x_mka_participant
*participant
, const u8
*mi
, u32 mn
)
607 struct ieee802_1x_kay_peer
*peer
;
609 peer
= ieee802_1x_kay_create_peer(mi
, mn
);
613 dl_list_add(&participant
->potential_peers
, &peer
->list
);
615 wpa_printf(MSG_DEBUG
, "KaY: potential peer created");
616 ieee802_1x_kay_dump_peer(peer
);
623 * ieee802_1x_kay_move_live_peer
625 static struct ieee802_1x_kay_peer
*
626 ieee802_1x_kay_move_live_peer(struct ieee802_1x_mka_participant
*participant
,
629 struct ieee802_1x_kay_peer
*peer
;
630 struct receive_sc
*rxsc
;
633 peer
= ieee802_1x_kay_get_potential_peer(participant
, mi
);
635 rxsc
= ieee802_1x_kay_init_receive_sc(&participant
->current_peer_sci
,
640 os_memcpy(&peer
->sci
, &participant
->current_peer_sci
,
643 peer
->expire
= time(NULL
) + MKA_LIFE_TIME
/ 1000;
645 wpa_printf(MSG_DEBUG
, "KaY: move potential peer to live peer");
646 ieee802_1x_kay_dump_peer(peer
);
648 dl_list_del(&peer
->list
);
649 dl_list_add_tail(&participant
->live_peers
, &peer
->list
);
651 secy_get_available_receive_sc(participant
->kay
, &sc_ch
);
653 dl_list_add(&participant
->rxsc_list
, &rxsc
->list
);
654 secy_create_receive_sc(participant
->kay
, rxsc
);
662 * ieee802_1x_mka_basic_body_present -
665 ieee802_1x_mka_basic_body_present(
666 struct ieee802_1x_mka_participant
*participant
)
673 * ieee802_1x_mka_basic_body_length -
676 ieee802_1x_mka_basic_body_length(struct ieee802_1x_mka_participant
*participant
)
680 length
= sizeof(struct ieee802_1x_mka_basic_body
);
681 length
+= participant
->ckn
.len
;
682 return MKA_ALIGN_LENGTH(length
);
687 * ieee802_1x_mka_encode_basic_body
690 ieee802_1x_mka_encode_basic_body(
691 struct ieee802_1x_mka_participant
*participant
,
694 struct ieee802_1x_mka_basic_body
*body
;
695 struct ieee802_1x_kay
*kay
= participant
->kay
;
696 unsigned int length
= ieee802_1x_mka_basic_body_length(participant
);
698 body
= wpabuf_put(buf
, length
);
700 body
->version
= kay
->mka_version
;
701 body
->priority
= kay
->actor_priority
;
702 if (participant
->is_elected
)
703 body
->key_server
= participant
->is_key_server
;
705 body
->key_server
= participant
->can_be_key_server
;
707 body
->macsec_desired
= kay
->macsec_desired
;
708 body
->macsec_capability
= kay
->macsec_capable
;
709 set_mka_param_body_len(body
, length
- MKA_HDR_LEN
);
711 os_memcpy(body
->actor_sci
.addr
, kay
->actor_sci
.addr
,
712 sizeof(kay
->actor_sci
.addr
));
713 body
->actor_sci
.port
= kay
->actor_sci
.port
;
715 os_memcpy(body
->actor_mi
, participant
->mi
, sizeof(body
->actor_mi
));
716 participant
->mn
= participant
->mn
+ 1;
717 body
->actor_mn
= host_to_be32(participant
->mn
);
718 os_memcpy(body
->algo_agility
, participant
->kay
->algo_agility
,
719 sizeof(body
->algo_agility
));
721 os_memcpy(body
->ckn
, participant
->ckn
.name
, participant
->ckn
.len
);
723 ieee802_1x_mka_dump_basic_body(body
);
730 reset_participant_mi(struct ieee802_1x_mka_participant
*participant
)
732 if (os_get_random(participant
->mi
, sizeof(participant
->mi
)) < 0)
741 * ieee802_1x_mka_decode_basic_body -
743 static struct ieee802_1x_mka_participant
*
744 ieee802_1x_mka_decode_basic_body(struct ieee802_1x_kay
*kay
, const u8
*mka_msg
,
747 struct ieee802_1x_mka_participant
*participant
;
748 const struct ieee802_1x_mka_basic_body
*body
;
749 struct ieee802_1x_kay_peer
*peer
;
751 body
= (const struct ieee802_1x_mka_basic_body
*) mka_msg
;
753 if (body
->version
> MKA_VERSION_ID
) {
754 wpa_printf(MSG_DEBUG
,
755 "KaY: peer's version(%d) greater than mka current version(%d)",
756 body
->version
, MKA_VERSION_ID
);
758 if (kay
->is_obliged_key_server
&& body
->key_server
) {
759 wpa_printf(MSG_DEBUG
, "I must be as key server");
763 participant
= ieee802_1x_kay_get_participant(kay
, body
->ckn
);
765 wpa_printf(MSG_DEBUG
, "Peer is not included in my CA");
769 /* If the peer's MI is my MI, I will choose new MI */
770 if (os_memcmp(body
->actor_mi
, participant
->mi
, MI_LEN
) == 0) {
771 if (!reset_participant_mi(participant
))
775 os_memcpy(participant
->current_peer_id
.mi
, body
->actor_mi
, MI_LEN
);
776 participant
->current_peer_id
.mn
= body
->actor_mn
;
777 os_memcpy(participant
->current_peer_sci
.addr
, body
->actor_sci
.addr
,
778 sizeof(participant
->current_peer_sci
.addr
));
779 participant
->current_peer_sci
.port
= body
->actor_sci
.port
;
782 peer
= ieee802_1x_kay_get_peer(participant
, body
->actor_mi
);
784 /* Check duplicated SCI */
785 /* TODO: What policy should be applied to detect duplicated SCI
786 * is active attacker or a valid peer whose MI is be changed?
788 peer
= ieee802_1x_kay_get_peer_sci(participant
,
791 wpa_printf(MSG_WARNING
,
792 "KaY: duplicated SCI detected, Maybe active attacker");
793 dl_list_del(&peer
->list
);
797 peer
= ieee802_1x_kay_create_potential_peer(
798 participant
, body
->actor_mi
,
799 be_to_host32(body
->actor_mn
));
803 peer
->macsec_desired
= body
->macsec_desired
;
804 peer
->macsec_capability
= body
->macsec_capability
;
805 peer
->is_key_server
= (Boolean
) body
->key_server
;
806 peer
->key_server_priority
= body
->priority
;
807 } else if (peer
->mn
< be_to_host32(body
->actor_mn
)) {
808 peer
->mn
= be_to_host32(body
->actor_mn
);
809 peer
->expire
= time(NULL
) + MKA_LIFE_TIME
/ 1000;
810 peer
->macsec_desired
= body
->macsec_desired
;
811 peer
->macsec_capability
= body
->macsec_capability
;
812 peer
->is_key_server
= (Boolean
) body
->key_server
;
813 peer
->key_server_priority
= body
->priority
;
815 wpa_printf(MSG_WARNING
, "KaY: The peer MN have received");
824 * ieee802_1x_mka_live_peer_body_present
827 ieee802_1x_mka_live_peer_body_present(
828 struct ieee802_1x_mka_participant
*participant
)
830 return !dl_list_empty(&participant
->live_peers
);
835 * ieee802_1x_kay_get_live_peer_length
838 ieee802_1x_mka_get_live_peer_length(
839 struct ieee802_1x_mka_participant
*participant
)
841 int len
= MKA_HDR_LEN
;
842 struct ieee802_1x_kay_peer
*peer
;
844 dl_list_for_each(peer
, &participant
->live_peers
,
845 struct ieee802_1x_kay_peer
, list
)
846 len
+= sizeof(struct ieee802_1x_mka_peer_id
);
848 return MKA_ALIGN_LENGTH(len
);
853 * ieee802_1x_mka_encode_live_peer_body -
856 ieee802_1x_mka_encode_live_peer_body(
857 struct ieee802_1x_mka_participant
*participant
,
860 struct ieee802_1x_mka_peer_body
*body
;
861 struct ieee802_1x_kay_peer
*peer
;
863 struct ieee802_1x_mka_peer_id
*body_peer
;
865 length
= ieee802_1x_mka_get_live_peer_length(participant
);
866 body
= wpabuf_put(buf
, sizeof(struct ieee802_1x_mka_peer_body
));
868 body
->type
= MKA_LIVE_PEER_LIST
;
869 set_mka_param_body_len(body
, length
- MKA_HDR_LEN
);
871 dl_list_for_each(peer
, &participant
->live_peers
,
872 struct ieee802_1x_kay_peer
, list
) {
873 body_peer
= wpabuf_put(buf
,
874 sizeof(struct ieee802_1x_mka_peer_id
));
875 os_memcpy(body_peer
->mi
, peer
->mi
, MI_LEN
);
876 body_peer
->mn
= host_to_be32(peer
->mn
);
879 ieee802_1x_mka_dump_peer_body(body
);
884 * ieee802_1x_mka_potential_peer_body_present
887 ieee802_1x_mka_potential_peer_body_present(
888 struct ieee802_1x_mka_participant
*participant
)
890 return !dl_list_empty(&participant
->potential_peers
);
895 * ieee802_1x_kay_get_potential_peer_length
898 ieee802_1x_mka_get_potential_peer_length(
899 struct ieee802_1x_mka_participant
*participant
)
901 int len
= MKA_HDR_LEN
;
902 struct ieee802_1x_kay_peer
*peer
;
904 dl_list_for_each(peer
, &participant
->potential_peers
,
905 struct ieee802_1x_kay_peer
, list
)
906 len
+= sizeof(struct ieee802_1x_mka_peer_id
);
908 return MKA_ALIGN_LENGTH(len
);
913 * ieee802_1x_mka_encode_potential_peer_body -
916 ieee802_1x_mka_encode_potential_peer_body(
917 struct ieee802_1x_mka_participant
*participant
,
920 struct ieee802_1x_mka_peer_body
*body
;
921 struct ieee802_1x_kay_peer
*peer
;
923 struct ieee802_1x_mka_peer_id
*body_peer
;
925 length
= ieee802_1x_mka_get_potential_peer_length(participant
);
926 body
= wpabuf_put(buf
, sizeof(struct ieee802_1x_mka_peer_body
));
928 body
->type
= MKA_POTENTIAL_PEER_LIST
;
929 set_mka_param_body_len(body
, length
- MKA_HDR_LEN
);
931 dl_list_for_each(peer
, &participant
->potential_peers
,
932 struct ieee802_1x_kay_peer
, list
) {
933 body_peer
= wpabuf_put(buf
,
934 sizeof(struct ieee802_1x_mka_peer_id
));
935 os_memcpy(body_peer
->mi
, peer
->mi
, MI_LEN
);
936 body_peer
->mn
= host_to_be32(peer
->mn
);
939 ieee802_1x_mka_dump_peer_body(body
);
945 * ieee802_1x_mka_i_in_peerlist -
948 ieee802_1x_mka_i_in_peerlist(struct ieee802_1x_mka_participant
*participant
,
949 const u8
*mka_msg
, size_t msg_len
)
951 struct ieee802_1x_mka_hdr
*hdr
;
958 for (pos
= mka_msg
, left_len
= msg_len
;
959 left_len
> MKA_HDR_LEN
+ DEFAULT_ICV_LEN
;
960 left_len
-= body_len
+ MKA_HDR_LEN
,
961 pos
+= body_len
+ MKA_HDR_LEN
) {
962 hdr
= (struct ieee802_1x_mka_hdr
*) pos
;
963 body_len
= get_mka_param_body_len(hdr
);
964 body_type
= get_mka_param_body_type(hdr
);
966 if (body_type
!= MKA_LIVE_PEER_LIST
&&
967 body_type
!= MKA_POTENTIAL_PEER_LIST
)
970 ieee802_1x_mka_dump_peer_body(
971 (struct ieee802_1x_mka_peer_body
*)pos
);
973 if (left_len
< (MKA_HDR_LEN
+ body_len
+ DEFAULT_ICV_LEN
)) {
974 wpa_printf(MSG_ERROR
,
975 "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",
976 left_len
, MKA_HDR_LEN
,
977 body_len
, DEFAULT_ICV_LEN
);
981 if ((body_len
% 16) != 0) {
982 wpa_printf(MSG_ERROR
,
983 "KaY: MKA Peer Packet Body Length (%zu bytes) should be a multiple of 16 octets",
988 for (i
= 0; i
< body_len
;
989 i
+= sizeof(struct ieee802_1x_mka_peer_id
)) {
990 const struct ieee802_1x_mka_peer_id
*peer_mi
;
992 peer_mi
= (const struct ieee802_1x_mka_peer_id
*)
993 (pos
+ MKA_HDR_LEN
+ i
);
994 if (os_memcmp(peer_mi
->mi
, participant
->mi
,
996 be_to_host32(peer_mi
->mn
) == participant
->mn
)
1006 * ieee802_1x_mka_decode_live_peer_body -
1008 static int ieee802_1x_mka_decode_live_peer_body(
1009 struct ieee802_1x_mka_participant
*participant
,
1010 const u8
*peer_msg
, size_t msg_len
)
1012 const struct ieee802_1x_mka_hdr
*hdr
;
1013 struct ieee802_1x_kay_peer
*peer
;
1016 Boolean is_included
;
1018 is_included
= ieee802_1x_kay_is_in_live_peer(
1019 participant
, participant
->current_peer_id
.mi
);
1021 hdr
= (const struct ieee802_1x_mka_hdr
*) peer_msg
;
1022 body_len
= get_mka_param_body_len(hdr
);
1023 if (body_len
% 16 != 0) {
1024 wpa_printf(MSG_ERROR
,
1025 "KaY: MKA Peer Packet Body Length (%zu bytes) should be a multiple of 16 octets",
1030 for (i
= 0; i
< body_len
; i
+= sizeof(struct ieee802_1x_mka_peer_id
)) {
1031 const struct ieee802_1x_mka_peer_id
*peer_mi
;
1034 peer_mi
= (const struct ieee802_1x_mka_peer_id
*)
1035 (peer_msg
+ MKA_HDR_LEN
+ i
);
1036 peer_mn
= be_to_host32(peer_mi
->mn
);
1039 if (os_memcmp(peer_mi
, participant
->mi
, MI_LEN
) == 0) {
1040 /* My message id is used by other participant */
1041 if (peer_mn
> participant
->mn
&&
1042 !reset_participant_mi(participant
))
1043 wpa_printf(MSG_DEBUG
, "KaY: Could not update mi");
1050 peer
= ieee802_1x_kay_get_peer(participant
, peer_mi
->mi
);
1053 peer
->expire
= time(NULL
) + MKA_LIFE_TIME
/ 1000;
1054 } else if (!ieee802_1x_kay_create_potential_peer(
1055 participant
, peer_mi
->mi
, peer_mn
)) {
1065 * ieee802_1x_mka_decode_potential_peer_body -
1068 ieee802_1x_mka_decode_potential_peer_body(
1069 struct ieee802_1x_mka_participant
*participant
,
1070 const u8
*peer_msg
, size_t msg_len
)
1072 struct ieee802_1x_mka_hdr
*hdr
;
1079 hdr
= (struct ieee802_1x_mka_hdr
*) peer_msg
;
1080 body_len
= get_mka_param_body_len(hdr
);
1081 if (body_len
% 16 != 0) {
1082 wpa_printf(MSG_ERROR
,
1083 "KaY: MKA Peer Packet Body Length (%zu bytes) should be a multiple of 16 octets",
1088 for (i
= 0; i
< body_len
; i
+= MI_LEN
+ sizeof(peer_mn
)) {
1089 peer_mi
= MKA_HDR_LEN
+ peer_msg
+ i
;
1090 os_memcpy(&_peer_mn
, peer_mi
+ MI_LEN
, sizeof(_peer_mn
));
1091 peer_mn
= be_to_host32(_peer_mn
);
1094 if (os_memcmp(peer_mi
, participant
->mi
, MI_LEN
) == 0) {
1095 /* My message id is used by other participant */
1096 if (peer_mn
> participant
->mn
&&
1097 !reset_participant_mi(participant
))
1098 wpa_printf(MSG_DEBUG
, "KaY: Could not update mi");
1108 * ieee802_1x_mka_sak_use_body_present
1111 ieee802_1x_mka_sak_use_body_present(
1112 struct ieee802_1x_mka_participant
*participant
)
1114 return participant
->to_use_sak
;
1119 * ieee802_1x_mka_get_sak_use_length
1122 ieee802_1x_mka_get_sak_use_length(
1123 struct ieee802_1x_mka_participant
*participant
)
1125 int length
= MKA_HDR_LEN
;
1127 if (participant
->kay
->macsec_desired
&& participant
->advised_desired
)
1128 length
= sizeof(struct ieee802_1x_mka_sak_use_body
);
1130 return MKA_ALIGN_LENGTH(length
);
1138 ieee802_1x_mka_get_lpn(struct ieee802_1x_mka_participant
*principal
,
1139 struct ieee802_1x_mka_ki
*ki
)
1141 struct receive_sa
*rxsa
;
1142 struct receive_sc
*rxsc
;
1145 dl_list_for_each(rxsc
, &principal
->rxsc_list
, struct receive_sc
, list
) {
1146 dl_list_for_each(rxsa
, &rxsc
->sa_list
, struct receive_sa
, list
)
1148 if (is_ki_equal(&rxsa
->pkey
->key_identifier
, ki
)) {
1149 secy_get_receive_lowest_pn(principal
->kay
,
1152 lpn
= lpn
> rxsa
->lowest_pn
?
1153 lpn
: rxsa
->lowest_pn
;
1167 * ieee802_1x_mka_encode_sak_use_body -
1170 ieee802_1x_mka_encode_sak_use_body(
1171 struct ieee802_1x_mka_participant
*participant
,
1174 struct ieee802_1x_mka_sak_use_body
*body
;
1175 unsigned int length
;
1178 length
= ieee802_1x_mka_get_sak_use_length(participant
);
1179 body
= wpabuf_put(buf
, length
);
1181 body
->type
= MKA_SAK_USE
;
1182 set_mka_param_body_len(body
, length
- MKA_HDR_LEN
);
1184 if (length
== MKA_HDR_LEN
) {
1190 body
->delay_protect
= FALSE
;
1194 /* data protect, lowest accept packet number */
1195 body
->delay_protect
= participant
->kay
->macsec_replay_protect
;
1196 pn
= ieee802_1x_mka_get_lpn(participant
, &participant
->lki
);
1197 if (pn
> participant
->kay
->pn_exhaustion
) {
1198 wpa_printf(MSG_WARNING
, "KaY: My LPN exhaustion");
1199 if (participant
->is_key_server
)
1200 participant
->new_sak
= TRUE
;
1203 body
->llpn
= host_to_be32(pn
);
1204 pn
= ieee802_1x_mka_get_lpn(participant
, &participant
->oki
);
1205 body
->olpn
= host_to_be32(pn
);
1207 /* plain tx, plain rx */
1208 if (participant
->kay
->macsec_protect
)
1213 if (participant
->kay
->macsec_validate
== Strict
)
1218 /* latest key: rx, tx, key server member identifier key number */
1219 body
->lan
= participant
->lan
;
1220 os_memcpy(body
->lsrv_mi
, participant
->lki
.mi
,
1221 sizeof(body
->lsrv_mi
));
1222 body
->lkn
= host_to_be32(participant
->lki
.kn
);
1223 body
->lrx
= participant
->lrx
;
1224 body
->ltx
= participant
->ltx
;
1226 /* old key: rx, tx, key server member identifier key number */
1227 body
->oan
= participant
->oan
;
1228 if (participant
->oki
.kn
!= participant
->lki
.kn
&&
1229 participant
->oki
.kn
!= 0) {
1232 os_memcpy(body
->osrv_mi
, participant
->oki
.mi
,
1233 sizeof(body
->osrv_mi
));
1234 body
->okn
= host_to_be32(participant
->oki
.kn
);
1240 /* set CP's variable */
1242 if (!participant
->kay
->tx_enable
)
1243 participant
->kay
->tx_enable
= TRUE
;
1245 if (!participant
->kay
->port_enable
)
1246 participant
->kay
->port_enable
= TRUE
;
1249 if (!participant
->kay
->rx_enable
)
1250 participant
->kay
->rx_enable
= TRUE
;
1253 ieee802_1x_mka_dump_sak_use_body(body
);
1259 * ieee802_1x_mka_decode_sak_use_body -
1262 ieee802_1x_mka_decode_sak_use_body(
1263 struct ieee802_1x_mka_participant
*participant
,
1264 const u8
*mka_msg
, size_t msg_len
)
1266 struct ieee802_1x_mka_hdr
*hdr
;
1267 struct ieee802_1x_mka_sak_use_body
*body
;
1268 struct ieee802_1x_kay_peer
*peer
;
1269 struct transmit_sa
*txsa
;
1270 struct data_key
*sa_key
= NULL
;
1272 struct ieee802_1x_mka_ki ki
;
1274 Boolean all_receiving
;
1277 if (!participant
->principal
) {
1278 wpa_printf(MSG_WARNING
, "KaY: Participant is not principal");
1281 peer
= ieee802_1x_kay_get_live_peer(participant
,
1282 participant
->current_peer_id
.mi
);
1284 wpa_printf(MSG_WARNING
, "KaY: the peer is not my live peer");
1288 hdr
= (struct ieee802_1x_mka_hdr
*) mka_msg
;
1289 body_len
= get_mka_param_body_len(hdr
);
1290 body
= (struct ieee802_1x_mka_sak_use_body
*) mka_msg
;
1291 ieee802_1x_mka_dump_sak_use_body(body
);
1293 if ((body_len
!= 0) && (body_len
< 40)) {
1294 wpa_printf(MSG_ERROR
,
1295 "KaY: MKA Use SAK Packet Body Length (%zu bytes) should be 0, 40, or more octets",
1300 /* TODO: what action should I take when peer does not support MACsec */
1301 if (body_len
== 0) {
1302 wpa_printf(MSG_WARNING
, "KaY: Peer does not support MACsec");
1306 /* TODO: when the plain tx or rx of peer is true, should I change
1307 * the attribute of controlled port
1310 wpa_printf(MSG_WARNING
, "KaY: peer's plain rx are TRUE");
1313 wpa_printf(MSG_WARNING
, "KaY: peer's plain tx are TRUE");
1315 /* check latest key is valid */
1316 if (body
->ltx
|| body
->lrx
) {
1318 os_memcpy(ki
.mi
, body
->lsrv_mi
, sizeof(ki
.mi
));
1319 ki
.kn
= be_to_host32(body
->lkn
);
1320 dl_list_for_each(sa_key
, &participant
->sak_list
,
1321 struct data_key
, list
) {
1322 if (is_ki_equal(&sa_key
->key_identifier
, &ki
)) {
1328 wpa_printf(MSG_WARNING
, "KaY: Latest key is invalid");
1331 if (os_memcmp(participant
->lki
.mi
, body
->lsrv_mi
,
1332 sizeof(participant
->lki
.mi
)) == 0 &&
1333 be_to_host32(body
->lkn
) == participant
->lki
.kn
&&
1334 body
->lan
== participant
->lan
) {
1335 peer
->sak_used
= TRUE
;
1337 if (body
->ltx
&& peer
->is_key_server
) {
1338 ieee802_1x_cp_set_servertransmitting(
1339 participant
->kay
->cp
, TRUE
);
1340 ieee802_1x_cp_sm_step(participant
->kay
->cp
);
1344 /* check old key is valid */
1345 if (body
->otx
|| body
->orx
) {
1346 if (os_memcmp(participant
->oki
.mi
, body
->osrv_mi
,
1347 sizeof(participant
->oki
.mi
)) != 0 ||
1348 be_to_host32(body
->okn
) != participant
->oki
.kn
||
1349 body
->oan
!= participant
->oan
) {
1350 wpa_printf(MSG_WARNING
, "KaY: Old key is invalid");
1355 /* TODO: how to set the MACsec hardware when delay_protect is true */
1356 if (body
->delay_protect
&&
1357 (!be_to_host32(body
->llpn
) || !be_to_host32(body
->olpn
))) {
1358 wpa_printf(MSG_WARNING
,
1359 "KaY: Lowest packet number should greater than 0 when delay_protect is TRUE");
1363 /* check all live peer have used the sak for receiving sa */
1364 all_receiving
= TRUE
;
1365 dl_list_for_each(peer
, &participant
->live_peers
,
1366 struct ieee802_1x_kay_peer
, list
) {
1367 if (!peer
->sak_used
) {
1368 all_receiving
= FALSE
;
1372 if (all_receiving
) {
1373 participant
->to_dist_sak
= FALSE
;
1374 ieee802_1x_cp_set_allreceiving(participant
->kay
->cp
, TRUE
);
1375 ieee802_1x_cp_sm_step(participant
->kay
->cp
);
1378 /* if i'm key server, and detects peer member pn exhaustion, rekey.*/
1379 lpn
= be_to_host32(body
->llpn
);
1380 if (lpn
> participant
->kay
->pn_exhaustion
) {
1381 if (participant
->is_key_server
) {
1382 participant
->new_sak
= TRUE
;
1383 wpa_printf(MSG_WARNING
, "KaY: Peer LPN exhaustion");
1388 dl_list_for_each(txsa
, &participant
->txsc
->sa_list
,
1389 struct transmit_sa
, list
) {
1390 if (sa_key
!= NULL
&& txsa
->pkey
== sa_key
) {
1396 wpa_printf(MSG_WARNING
, "KaY: Can't find txsa");
1400 /* FIXME: Secy creates txsa with default npn. If MKA detected Latest Key
1401 * npn is larger than txsa's npn, set it to txsa.
1403 secy_get_transmit_next_pn(participant
->kay
, txsa
);
1404 if (lpn
> txsa
->next_pn
) {
1405 secy_set_transmit_next_pn(participant
->kay
, txsa
);
1406 wpa_printf(MSG_INFO
, "KaY: update lpn =0x%x", lpn
);
1414 * ieee802_1x_mka_dist_sak_body_present
1417 ieee802_1x_mka_dist_sak_body_present(
1418 struct ieee802_1x_mka_participant
*participant
)
1420 if (!participant
->to_dist_sak
|| !participant
->new_key
)
1428 * ieee802_1x_kay_get_dist_sak_length
1431 ieee802_1x_mka_get_dist_sak_length(
1432 struct ieee802_1x_mka_participant
*participant
)
1434 int length
= MKA_HDR_LEN
;
1435 int cs_index
= participant
->kay
->macsec_csindex
;
1437 if (participant
->advised_desired
) {
1438 length
= sizeof(struct ieee802_1x_mka_dist_sak_body
);
1439 if (cs_index
!= DEFAULT_CS_INDEX
)
1440 length
+= CS_ID_LEN
;
1442 length
+= cipher_suite_tbl
[cs_index
].sak_len
+ 8;
1445 return MKA_ALIGN_LENGTH(length
);
1450 * ieee802_1x_mka_encode_dist_sak_body -
1453 ieee802_1x_mka_encode_dist_sak_body(
1454 struct ieee802_1x_mka_participant
*participant
,
1457 struct ieee802_1x_mka_dist_sak_body
*body
;
1458 struct data_key
*sak
;
1459 unsigned int length
;
1463 length
= ieee802_1x_mka_get_dist_sak_length(participant
);
1464 body
= wpabuf_put(buf
, length
);
1465 body
->type
= MKA_DISTRIBUTED_SAK
;
1466 set_mka_param_body_len(body
, length
- MKA_HDR_LEN
);
1467 if (length
== MKA_HDR_LEN
) {
1468 body
->confid_offset
= 0;
1473 sak
= participant
->new_key
;
1474 body
->confid_offset
= sak
->confidentiality_offset
;
1475 body
->dan
= sak
->an
;
1476 body
->kn
= host_to_be32(sak
->key_identifier
.kn
);
1477 cs_index
= participant
->kay
->macsec_csindex
;
1479 if (cs_index
!= DEFAULT_CS_INDEX
) {
1480 os_memcpy(body
->sak
, cipher_suite_tbl
[cs_index
].id
, CS_ID_LEN
);
1481 sak_pos
= CS_ID_LEN
;
1483 if (aes_wrap(participant
->kek
.key
, 16,
1484 cipher_suite_tbl
[cs_index
].sak_len
/ 8,
1485 sak
->key
, body
->sak
+ sak_pos
)) {
1486 wpa_printf(MSG_ERROR
, "KaY: AES wrap failed");
1490 ieee802_1x_mka_dump_dist_sak_body(body
);
1497 * ieee802_1x_kay_init_data_key -
1499 static struct data_key
*
1500 ieee802_1x_kay_init_data_key(const struct key_conf
*conf
)
1502 struct data_key
*pkey
;
1507 pkey
= os_zalloc(sizeof(*pkey
));
1509 wpa_printf(MSG_ERROR
, "%s: out of memory", __func__
);
1513 pkey
->key
= os_zalloc(conf
->key_len
);
1514 if (pkey
->key
== NULL
) {
1515 wpa_printf(MSG_ERROR
, "%s: out of memory", __func__
);
1520 os_memcpy(pkey
->key
, conf
->key
, conf
->key_len
);
1521 os_memcpy(&pkey
->key_identifier
, &conf
->ki
,
1522 sizeof(pkey
->key_identifier
));
1523 pkey
->confidentiality_offset
= conf
->offset
;
1524 pkey
->an
= conf
->an
;
1525 pkey
->transmits
= conf
->tx
;
1526 pkey
->receives
= conf
->rx
;
1527 os_get_time(&pkey
->created_time
);
1536 * ieee802_1x_kay_decode_dist_sak_body -
1539 ieee802_1x_mka_decode_dist_sak_body(
1540 struct ieee802_1x_mka_participant
*participant
,
1541 const u8
*mka_msg
, size_t msg_len
)
1543 struct ieee802_1x_mka_hdr
*hdr
;
1544 struct ieee802_1x_mka_dist_sak_body
*body
;
1545 struct ieee802_1x_kay_peer
*peer
;
1546 struct macsec_ciphersuite
*cs
;
1548 struct key_conf
*conf
;
1549 struct data_key
*sa_key
= NULL
;
1550 struct ieee802_1x_mka_ki sak_ki
;
1555 hdr
= (struct ieee802_1x_mka_hdr
*) mka_msg
;
1556 body_len
= get_mka_param_body_len(hdr
);
1557 if ((body_len
!= 0) && (body_len
!= 28) && (body_len
< 36)) {
1558 wpa_printf(MSG_ERROR
,
1559 "KaY: MKA Use SAK Packet Body Length (%zu bytes) should be 0, 28, 36, or more octets",
1564 if (!participant
->principal
) {
1565 wpa_printf(MSG_ERROR
,
1566 "KaY: I can't accept the distributed SAK as I am not principal");
1569 if (participant
->is_key_server
) {
1570 wpa_printf(MSG_ERROR
,
1571 "KaY: I can't accept the distributed SAK as myself is key server ");
1574 if (!participant
->kay
->macsec_desired
||
1575 participant
->kay
->macsec_capable
== MACSEC_CAP_NOT_IMPLEMENTED
) {
1576 wpa_printf(MSG_ERROR
,
1577 "KaY: I am not MACsec-desired or without MACsec capable");
1581 peer
= ieee802_1x_kay_get_live_peer(participant
,
1582 participant
->current_peer_id
.mi
);
1584 wpa_printf(MSG_ERROR
,
1585 "KaY: The key server is not in my live peers list");
1588 if (!sci_equal(&participant
->kay
->key_server_sci
, &peer
->sci
)) {
1589 wpa_printf(MSG_ERROR
, "KaY: The key server is not elected");
1592 if (body_len
== 0) {
1593 participant
->kay
->authenticated
= TRUE
;
1594 participant
->kay
->secured
= FALSE
;
1595 participant
->kay
->failed
= FALSE
;
1596 participant
->advised_desired
= FALSE
;
1597 ieee802_1x_cp_connect_authenticated(participant
->kay
->cp
);
1598 ieee802_1x_cp_sm_step(participant
->kay
->cp
);
1599 wpa_printf(MSG_WARNING
, "KaY:The Key server advise no MACsec");
1600 participant
->to_use_sak
= TRUE
;
1603 participant
->advised_desired
= TRUE
;
1604 participant
->kay
->authenticated
= FALSE
;
1605 participant
->kay
->secured
= TRUE
;
1606 participant
->kay
->failed
= FALSE
;
1607 ieee802_1x_cp_connect_secure(participant
->kay
->cp
);
1608 ieee802_1x_cp_sm_step(participant
->kay
->cp
);
1610 body
= (struct ieee802_1x_mka_dist_sak_body
*)mka_msg
;
1611 ieee802_1x_mka_dump_dist_sak_body(body
);
1612 dl_list_for_each(sa_key
, &participant
->sak_list
, struct data_key
, list
)
1614 if (os_memcmp(sa_key
->key_identifier
.mi
,
1615 participant
->current_peer_id
.mi
, MI_LEN
) == 0 &&
1616 sa_key
->key_identifier
.kn
== be_to_host32(body
->kn
)) {
1617 wpa_printf(MSG_WARNING
, "KaY:The Key has installed");
1621 if (body_len
== 28) {
1622 sak_len
= DEFAULT_SA_KEY_LEN
;
1623 wrap_sak
= body
->sak
;
1624 participant
->kay
->macsec_csindex
= DEFAULT_CS_INDEX
;
1626 cs
= ieee802_1x_kay_get_cipher_suite(participant
, body
->sak
);
1628 wpa_printf(MSG_ERROR
,
1629 "KaY: I can't support the Cipher Suite advised by key server");
1632 sak_len
= cs
->sak_len
;
1633 wrap_sak
= body
->sak
+ CS_ID_LEN
;
1634 participant
->kay
->macsec_csindex
= cs
->index
;
1637 unwrap_sak
= os_zalloc(sak_len
);
1639 wpa_printf(MSG_ERROR
, "KaY-%s: Out of memory", __func__
);
1642 if (aes_unwrap(participant
->kek
.key
, 16, sak_len
>> 3, wrap_sak
,
1644 wpa_printf(MSG_ERROR
, "KaY: AES unwrap failed");
1645 os_free(unwrap_sak
);
1648 wpa_hexdump(MSG_DEBUG
, "\tAES Key Unwrap of SAK:", unwrap_sak
, sak_len
);
1650 conf
= os_zalloc(sizeof(*conf
));
1652 wpa_printf(MSG_ERROR
, "KaY-%s: Out of memory", __func__
);
1653 os_free(unwrap_sak
);
1656 conf
->key_len
= sak_len
;
1658 conf
->key
= os_zalloc(conf
->key_len
);
1660 wpa_printf(MSG_ERROR
, "KaY-%s: Out of memory", __func__
);
1661 os_free(unwrap_sak
);
1666 os_memcpy(conf
->key
, unwrap_sak
, conf
->key_len
);
1668 os_memcpy(&sak_ki
.mi
, &participant
->current_peer_id
.mi
,
1670 sak_ki
.kn
= be_to_host32(body
->kn
);
1672 os_memcpy(conf
->ki
.mi
, sak_ki
.mi
, MI_LEN
);
1673 conf
->ki
.kn
= sak_ki
.kn
;
1674 conf
->an
= body
->dan
;
1675 conf
->offset
= body
->confid_offset
;
1679 sa_key
= ieee802_1x_kay_init_data_key(conf
);
1681 os_free(unwrap_sak
);
1687 dl_list_add(&participant
->sak_list
, &sa_key
->list
);
1689 ieee802_1x_cp_set_ciphersuite(
1690 participant
->kay
->cp
,
1691 cipher_suite_tbl
[participant
->kay
->macsec_csindex
].id
);
1692 ieee802_1x_cp_sm_step(participant
->kay
->cp
);
1693 ieee802_1x_cp_set_offset(participant
->kay
->cp
, body
->confid_offset
);
1694 ieee802_1x_cp_sm_step(participant
->kay
->cp
);
1695 ieee802_1x_cp_set_distributedki(participant
->kay
->cp
, &sak_ki
);
1696 ieee802_1x_cp_set_distributedan(participant
->kay
->cp
, body
->dan
);
1697 ieee802_1x_cp_signal_newsak(participant
->kay
->cp
);
1698 ieee802_1x_cp_sm_step(participant
->kay
->cp
);
1700 participant
->to_use_sak
= TRUE
;
1702 os_free(unwrap_sak
);
1711 * ieee802_1x_mka_icv_body_present
1714 ieee802_1x_mka_icv_body_present(struct ieee802_1x_mka_participant
*participant
)
1721 * ieee802_1x_kay_get_icv_length
1724 ieee802_1x_mka_get_icv_length(struct ieee802_1x_mka_participant
*participant
)
1728 length
= sizeof(struct ieee802_1x_mka_icv_body
);
1729 length
+= mka_alg_tbl
[participant
->kay
->mka_algindex
].icv_len
;
1731 return MKA_ALIGN_LENGTH(length
);
1736 * ieee802_1x_mka_encode_icv_body -
1739 ieee802_1x_mka_encode_icv_body(struct ieee802_1x_mka_participant
*participant
,
1742 struct ieee802_1x_mka_icv_body
*body
;
1743 unsigned int length
;
1744 u8 cmac
[MAX_ICV_LEN
];
1746 length
= ieee802_1x_mka_get_icv_length(participant
);
1747 if (length
!= DEFAULT_ICV_LEN
) {
1748 body
= wpabuf_put(buf
, MKA_HDR_LEN
);
1749 body
->type
= MKA_ICV_INDICATOR
;
1750 set_mka_param_body_len(body
, length
- MKA_HDR_LEN
);
1753 if (mka_alg_tbl
[participant
->kay
->mka_algindex
].icv_hash(
1754 participant
->ick
.key
, wpabuf_head(buf
), buf
->used
, cmac
)) {
1755 wpa_printf(MSG_ERROR
, "KaY, omac1_aes_128 failed");
1759 if (length
!= DEFAULT_ICV_LEN
)
1760 length
-= MKA_HDR_LEN
;
1761 os_memcpy(wpabuf_put(buf
, length
), cmac
, length
);
1767 * ieee802_1x_mka_decode_icv_body -
1770 ieee802_1x_mka_decode_icv_body(struct ieee802_1x_mka_participant
*participant
,
1771 const u8
*mka_msg
, size_t msg_len
)
1773 struct ieee802_1x_mka_hdr
*hdr
;
1774 struct ieee802_1x_mka_icv_body
*body
;
1782 while (left_len
> (MKA_HDR_LEN
+ DEFAULT_ICV_LEN
)) {
1783 hdr
= (struct ieee802_1x_mka_hdr
*) pos
;
1784 body_len
= get_mka_param_body_len(hdr
);
1785 body_type
= get_mka_param_body_type(hdr
);
1787 if (left_len
< (body_len
+ MKA_HDR_LEN
))
1790 if (body_type
!= MKA_ICV_INDICATOR
) {
1791 left_len
-= MKA_HDR_LEN
+ body_len
;
1792 pos
+= MKA_HDR_LEN
+ body_len
;
1796 body
= (struct ieee802_1x_mka_icv_body
*)pos
;
1798 < mka_alg_tbl
[participant
->kay
->mka_algindex
].icv_len
) {
1805 return (u8
*) (mka_msg
+ msg_len
- DEFAULT_ICV_LEN
);
1810 * ieee802_1x_mka_decode_dist_cak_body-
1813 ieee802_1x_mka_decode_dist_cak_body(
1814 struct ieee802_1x_mka_participant
*participant
,
1815 const u8
*mka_msg
, size_t msg_len
)
1817 struct ieee802_1x_mka_hdr
*hdr
;
1820 hdr
= (struct ieee802_1x_mka_hdr
*) mka_msg
;
1821 body_len
= get_mka_param_body_len(hdr
);
1822 if (body_len
< 28) {
1823 wpa_printf(MSG_ERROR
,
1824 "KaY: MKA Use SAK Packet Body Length (%zu bytes) should be 28 or more octets",
1834 * ieee802_1x_mka_decode_kmd_body -
1837 ieee802_1x_mka_decode_kmd_body(
1838 struct ieee802_1x_mka_participant
*participant
,
1839 const u8
*mka_msg
, size_t msg_len
)
1841 struct ieee802_1x_mka_hdr
*hdr
;
1844 hdr
= (struct ieee802_1x_mka_hdr
*) mka_msg
;
1845 body_len
= get_mka_param_body_len(hdr
);
1847 wpa_printf(MSG_ERROR
,
1848 "KaY: MKA Use SAK Packet Body Length (%zu bytes) should be 5 or more octets",
1858 * ieee802_1x_mka_decode_announce_body -
1860 static int ieee802_1x_mka_decode_announce_body(
1861 struct ieee802_1x_mka_participant
*participant
,
1862 const u8
*mka_msg
, size_t msg_len
)
1868 static struct mka_param_body_handler mka_body_handler
[] = {
1869 /* basic parameter set */
1871 ieee802_1x_mka_encode_basic_body
,
1873 ieee802_1x_mka_basic_body_length
,
1874 ieee802_1x_mka_basic_body_present
1877 /* live peer list parameter set */
1879 ieee802_1x_mka_encode_live_peer_body
,
1880 ieee802_1x_mka_decode_live_peer_body
,
1881 ieee802_1x_mka_get_live_peer_length
,
1882 ieee802_1x_mka_live_peer_body_present
1885 /* potential peer list parameter set */
1887 ieee802_1x_mka_encode_potential_peer_body
,
1888 ieee802_1x_mka_decode_potential_peer_body
,
1889 ieee802_1x_mka_get_potential_peer_length
,
1890 ieee802_1x_mka_potential_peer_body_present
1893 /* sak use parameter set */
1895 ieee802_1x_mka_encode_sak_use_body
,
1896 ieee802_1x_mka_decode_sak_use_body
,
1897 ieee802_1x_mka_get_sak_use_length
,
1898 ieee802_1x_mka_sak_use_body_present
1901 /* distribute sak parameter set */
1903 ieee802_1x_mka_encode_dist_sak_body
,
1904 ieee802_1x_mka_decode_dist_sak_body
,
1905 ieee802_1x_mka_get_dist_sak_length
,
1906 ieee802_1x_mka_dist_sak_body_present
1909 /* distribute cak parameter set */
1912 ieee802_1x_mka_decode_dist_cak_body
,
1917 /* kmd parameter set */
1920 ieee802_1x_mka_decode_kmd_body
,
1925 /* announce parameter set */
1928 ieee802_1x_mka_decode_announce_body
,
1933 /* icv parameter set */
1935 ieee802_1x_mka_encode_icv_body
,
1937 ieee802_1x_mka_get_icv_length
,
1938 ieee802_1x_mka_icv_body_present
1944 * ieee802_1x_kay_deinit_data_key -
1946 static void ieee802_1x_kay_deinit_data_key(struct data_key
*pkey
)
1955 dl_list_del(&pkey
->list
);
1962 * ieee802_1x_kay_generate_new_sak -
1965 ieee802_1x_kay_generate_new_sak(struct ieee802_1x_mka_participant
*participant
)
1967 struct data_key
*sa_key
= NULL
;
1968 struct key_conf
*conf
;
1969 struct ieee802_1x_kay_peer
*peer
;
1970 struct ieee802_1x_kay
*kay
= participant
->kay
;
1971 int ctx_len
, ctx_offset
;
1974 /* check condition for generating a fresh SAK:
1975 * must have one live peer
1976 * and MKA life time elapse since last distribution
1977 * or potential peer is empty
1979 if (dl_list_empty(&participant
->live_peers
)) {
1980 wpa_printf(MSG_ERROR
,
1981 "KaY: Live peers list must not empty when generating fresh SAK");
1985 /* FIXME: A fresh SAK not generated until
1986 * the live peer list contains at least one peer and
1987 * MKA life time has elapsed since the prior SAK was first distributed,
1988 * or the Key server's potential peer is empty
1989 * but I can't understand the second item, so
1990 * here only check first item and ingore
1991 * && (!dl_list_empty(&participant->potential_peers))) {
1993 if ((time(NULL
) - kay
->dist_time
) < MKA_LIFE_TIME
/ 1000) {
1994 wpa_printf(MSG_ERROR
,
1995 "KaY: Life time have not elapsed since prior SAK distributed");
1999 conf
= os_zalloc(sizeof(*conf
));
2001 wpa_printf(MSG_ERROR
, "KaY-%s: Out of memory", __func__
);
2004 conf
->key_len
= cipher_suite_tbl
[kay
->macsec_csindex
].sak_len
;
2006 conf
->key
= os_zalloc(conf
->key_len
);
2009 wpa_printf(MSG_ERROR
, "KaY-%s: Out of memory", __func__
);
2013 ctx_len
= conf
->key_len
+ sizeof(kay
->dist_kn
);
2014 dl_list_for_each(peer
, &participant
->live_peers
,
2015 struct ieee802_1x_kay_peer
, list
)
2016 ctx_len
+= sizeof(peer
->mi
);
2017 ctx_len
+= sizeof(participant
->mi
);
2019 context
= os_zalloc(ctx_len
);
2026 if (os_get_random(context
+ ctx_offset
, conf
->key_len
) < 0) {
2032 ctx_offset
+= conf
->key_len
;
2033 dl_list_for_each(peer
, &participant
->live_peers
,
2034 struct ieee802_1x_kay_peer
, list
) {
2035 os_memcpy(context
+ ctx_offset
, peer
->mi
, sizeof(peer
->mi
));
2036 ctx_offset
+= sizeof(peer
->mi
);
2038 os_memcpy(context
+ ctx_offset
, participant
->mi
,
2039 sizeof(participant
->mi
));
2040 ctx_offset
+= sizeof(participant
->mi
);
2041 os_memcpy(context
+ ctx_offset
, &kay
->dist_kn
, sizeof(kay
->dist_kn
));
2043 if (conf
->key_len
== 16) {
2044 ieee802_1x_sak_128bits_aes_cmac(participant
->cak
.key
,
2045 context
, ctx_len
, conf
->key
);
2046 } else if (conf
->key_len
== 32) {
2047 ieee802_1x_sak_128bits_aes_cmac(participant
->cak
.key
,
2048 context
, ctx_len
, conf
->key
);
2050 wpa_printf(MSG_ERROR
, "KaY: SAK Length not support");
2056 wpa_hexdump(MSG_DEBUG
, "KaY: generated new SAK",
2057 conf
->key
, conf
->key_len
);
2059 os_memcpy(conf
->ki
.mi
, participant
->mi
, MI_LEN
);
2060 conf
->ki
.kn
= participant
->kay
->dist_kn
;
2061 conf
->an
= participant
->kay
->dist_an
;
2062 conf
->offset
= kay
->macsec_confidentiality
;
2066 sa_key
= ieee802_1x_kay_init_data_key(conf
);
2073 participant
->new_key
= sa_key
;
2075 dl_list_add(&participant
->sak_list
, &sa_key
->list
);
2076 ieee802_1x_cp_set_ciphersuite(participant
->kay
->cp
,
2077 cipher_suite_tbl
[kay
->macsec_csindex
].id
);
2078 ieee802_1x_cp_sm_step(kay
->cp
);
2079 ieee802_1x_cp_set_offset(kay
->cp
, conf
->offset
);
2080 ieee802_1x_cp_sm_step(kay
->cp
);
2081 ieee802_1x_cp_set_distributedki(kay
->cp
, &conf
->ki
);
2082 ieee802_1x_cp_set_distributedan(kay
->cp
, conf
->an
);
2083 ieee802_1x_cp_signal_newsak(kay
->cp
);
2084 ieee802_1x_cp_sm_step(kay
->cp
);
2086 dl_list_for_each(peer
, &participant
->live_peers
,
2087 struct ieee802_1x_kay_peer
, list
)
2088 peer
->sak_used
= FALSE
;
2090 participant
->kay
->dist_kn
++;
2091 participant
->kay
->dist_an
++;
2092 if (participant
->kay
->dist_an
> 3)
2093 participant
->kay
->dist_an
= 0;
2095 participant
->kay
->dist_time
= time(NULL
);
2105 * ieee802_1x_kay_elect_key_server - elect the key server
2106 * when to elect: whenever the live peers list changes
2109 ieee802_1x_kay_elect_key_server(struct ieee802_1x_mka_participant
*participant
)
2111 struct ieee802_1x_kay_peer
*peer
;
2112 struct ieee802_1x_kay_peer
*key_server
= NULL
;
2113 struct ieee802_1x_kay
*kay
= participant
->kay
;
2114 Boolean i_is_key_server
;
2116 if (participant
->is_obliged_key_server
) {
2117 participant
->new_sak
= TRUE
;
2118 participant
->to_dist_sak
= FALSE
;
2119 ieee802_1x_cp_set_electedself(kay
->cp
, TRUE
);
2123 /* elect the key server among the peers */
2124 dl_list_for_each(peer
, &participant
->live_peers
,
2125 struct ieee802_1x_kay_peer
, list
) {
2126 if (!peer
->is_key_server
)
2134 if (peer
->key_server_priority
<
2135 key_server
->key_server_priority
) {
2137 } else if (peer
->key_server_priority
==
2138 key_server
->key_server_priority
) {
2139 if (os_memcmp(peer
->sci
.addr
, key_server
->sci
.addr
,
2145 /* elect the key server between me and the above elected peer */
2146 i_is_key_server
= FALSE
;
2147 if (key_server
&& participant
->can_be_key_server
) {
2148 if (kay
->actor_priority
2149 < key_server
->key_server_priority
) {
2150 i_is_key_server
= TRUE
;
2151 } else if (kay
->actor_priority
2152 == key_server
->key_server_priority
) {
2153 if (os_memcmp(kay
->actor_sci
.addr
, key_server
->sci
.addr
,
2155 i_is_key_server
= TRUE
;
2157 } else if (participant
->can_be_key_server
) {
2158 i_is_key_server
= TRUE
;
2161 if (i_is_key_server
) {
2162 ieee802_1x_cp_set_electedself(kay
->cp
, TRUE
);
2163 if (!sci_equal(&kay
->key_server_sci
, &kay
->actor_sci
)) {
2164 ieee802_1x_cp_signal_chgdserver(kay
->cp
);
2165 ieee802_1x_cp_sm_step(kay
->cp
);
2168 participant
->is_key_server
= TRUE
;
2169 participant
->principal
= TRUE
;
2170 participant
->new_sak
= TRUE
;
2171 wpa_printf(MSG_DEBUG
, "KaY: I is elected as key server");
2172 participant
->to_dist_sak
= FALSE
;
2173 participant
->is_elected
= TRUE
;
2175 os_memcpy(&kay
->key_server_sci
, &kay
->actor_sci
,
2176 sizeof(kay
->key_server_sci
));
2177 kay
->key_server_priority
= kay
->actor_priority
;
2178 } else if (key_server
) {
2179 ieee802_1x_cp_set_electedself(kay
->cp
, FALSE
);
2180 if (!sci_equal(&kay
->key_server_sci
, &key_server
->sci
)) {
2181 ieee802_1x_cp_signal_chgdserver(kay
->cp
);
2182 ieee802_1x_cp_sm_step(kay
->cp
);
2185 participant
->is_key_server
= FALSE
;
2186 participant
->principal
= TRUE
;
2187 participant
->is_elected
= TRUE
;
2189 os_memcpy(&kay
->key_server_sci
, &key_server
->sci
,
2190 sizeof(kay
->key_server_sci
));
2191 kay
->key_server_priority
= key_server
->key_server_priority
;
2193 participant
->principal
= FALSE
;
2194 participant
->is_key_server
= FALSE
;
2195 participant
->is_elected
= FALSE
;
2203 * ieee802_1x_kay_decide_macsec_use - the key server determinate
2204 * how to use MACsec: whether use MACsec and its capability
2205 * protectFrames will be advised if the key server and one of its live peers are
2206 * MACsec capable and one of those request MACsec protection
2209 ieee802_1x_kay_decide_macsec_use(
2210 struct ieee802_1x_mka_participant
*participant
)
2212 struct ieee802_1x_kay
*kay
= participant
->kay
;
2213 struct ieee802_1x_kay_peer
*peer
;
2214 enum macsec_cap less_capability
;
2217 if (!participant
->is_key_server
)
2220 /* key server self is MACsec-desired and requesting MACsec */
2221 if (!kay
->macsec_desired
) {
2222 participant
->advised_desired
= FALSE
;
2225 if (kay
->macsec_capable
== MACSEC_CAP_NOT_IMPLEMENTED
) {
2226 participant
->advised_desired
= FALSE
;
2229 less_capability
= kay
->macsec_capable
;
2231 /* at least one of peers is MACsec-desired and requesting MACsec */
2233 dl_list_for_each(peer
, &participant
->live_peers
,
2234 struct ieee802_1x_kay_peer
, list
) {
2235 if (!peer
->macsec_desired
)
2238 if (peer
->macsec_capability
== MACSEC_CAP_NOT_IMPLEMENTED
)
2241 less_capability
= (less_capability
< peer
->macsec_capability
) ?
2242 less_capability
: peer
->macsec_capability
;
2247 participant
->advised_desired
= TRUE
;
2248 participant
->advised_capability
= less_capability
;
2249 kay
->authenticated
= FALSE
;
2250 kay
->secured
= TRUE
;
2251 kay
->failed
= FALSE
;
2252 ieee802_1x_cp_connect_secure(kay
->cp
);
2253 ieee802_1x_cp_sm_step(kay
->cp
);
2255 participant
->advised_desired
= FALSE
;
2256 participant
->advised_capability
= MACSEC_CAP_NOT_IMPLEMENTED
;
2257 participant
->to_use_sak
= FALSE
;
2258 kay
->authenticated
= TRUE
;
2259 kay
->secured
= FALSE
;
2260 kay
->failed
= FALSE
;
2269 ieee802_1x_cp_connect_authenticated(kay
->cp
);
2270 ieee802_1x_cp_sm_step(kay
->cp
);
2276 static const u8 pae_group_addr
[ETH_ALEN
] = {
2277 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03
2282 * ieee802_1x_kay_encode_mkpdu -
2285 ieee802_1x_kay_encode_mkpdu(struct ieee802_1x_mka_participant
*participant
,
2286 struct wpabuf
*pbuf
)
2289 struct ieee8023_hdr
*ether_hdr
;
2290 struct ieee802_1x_hdr
*eapol_hdr
;
2292 ether_hdr
= wpabuf_put(pbuf
, sizeof(*ether_hdr
));
2293 os_memcpy(ether_hdr
->dest
, pae_group_addr
, sizeof(ether_hdr
->dest
));
2294 os_memcpy(ether_hdr
->src
, participant
->kay
->actor_sci
.addr
,
2295 sizeof(ether_hdr
->dest
));
2296 ether_hdr
->ethertype
= host_to_be16(ETH_P_EAPOL
);
2298 eapol_hdr
= wpabuf_put(pbuf
, sizeof(*eapol_hdr
));
2299 eapol_hdr
->version
= EAPOL_VERSION
;
2300 eapol_hdr
->type
= IEEE802_1X_TYPE_EAPOL_MKA
;
2301 eapol_hdr
->length
= host_to_be16(pbuf
->size
- pbuf
->used
);
2303 for (i
= 0; i
< ARRAY_SIZE(mka_body_handler
); i
++) {
2304 if (mka_body_handler
[i
].body_present
&&
2305 mka_body_handler
[i
].body_present(participant
)) {
2306 if (mka_body_handler
[i
].body_tx(participant
, pbuf
))
2315 * ieee802_1x_participant_send_mkpdu -
2318 ieee802_1x_participant_send_mkpdu(
2319 struct ieee802_1x_mka_participant
*participant
)
2322 struct ieee802_1x_kay
*kay
= participant
->kay
;
2326 wpa_printf(MSG_DEBUG
, "KaY: to enpacket and send the MKPDU");
2327 length
+= sizeof(struct ieee802_1x_hdr
) + sizeof(struct ieee8023_hdr
);
2328 for (i
= 0; i
< ARRAY_SIZE(mka_body_handler
); i
++) {
2329 if (mka_body_handler
[i
].body_present
&&
2330 mka_body_handler
[i
].body_present(participant
))
2331 length
+= mka_body_handler
[i
].body_length(participant
);
2334 buf
= wpabuf_alloc(length
);
2336 wpa_printf(MSG_ERROR
, "KaY: out of memory");
2340 if (ieee802_1x_kay_encode_mkpdu(participant
, buf
)) {
2341 wpa_printf(MSG_ERROR
, "KaY: encode mkpdu fail!");
2345 l2_packet_send(kay
->l2_mka
, NULL
, 0, wpabuf_head(buf
), wpabuf_len(buf
));
2349 participant
->active
= TRUE
;
2355 static void ieee802_1x_kay_deinit_transmit_sa(struct transmit_sa
*psa
);
2357 * ieee802_1x_participant_timer -
2359 static void ieee802_1x_participant_timer(void *eloop_ctx
, void *timeout_ctx
)
2361 struct ieee802_1x_mka_participant
*participant
;
2362 struct ieee802_1x_kay
*kay
;
2363 struct ieee802_1x_kay_peer
*peer
, *pre_peer
;
2364 time_t now
= time(NULL
);
2366 struct receive_sc
*rxsc
, *pre_rxsc
;
2367 struct transmit_sa
*txsa
, *pre_txsa
;
2369 participant
= (struct ieee802_1x_mka_participant
*)eloop_ctx
;
2370 kay
= participant
->kay
;
2371 if (participant
->cak_life
) {
2372 if (now
> participant
->cak_life
) {
2373 kay
->authenticated
= FALSE
;
2374 kay
->secured
= FALSE
;
2376 ieee802_1x_kay_delete_mka(kay
, &participant
->ckn
);
2381 /* should delete MKA instance if there are not live peers
2382 * when the MKA life elapsed since its creating */
2383 if (participant
->mka_life
) {
2384 if (dl_list_empty(&participant
->live_peers
)) {
2385 if (now
> participant
->mka_life
) {
2386 kay
->authenticated
= FALSE
;
2387 kay
->secured
= FALSE
;
2389 ieee802_1x_kay_delete_mka(kay
,
2394 participant
->mka_life
= 0;
2399 dl_list_for_each_safe(peer
, pre_peer
, &participant
->live_peers
,
2400 struct ieee802_1x_kay_peer
, list
) {
2401 if (now
> peer
->expire
) {
2402 wpa_printf(MSG_DEBUG
, "KaY: Live peer removed");
2403 wpa_hexdump(MSG_DEBUG
, "\tMI: ", peer
->mi
,
2405 wpa_printf(MSG_DEBUG
, "\tMN: %d", peer
->mn
);
2406 dl_list_for_each_safe(rxsc
, pre_rxsc
,
2407 &participant
->rxsc_list
,
2408 struct receive_sc
, list
) {
2409 if (sci_equal(&rxsc
->sci
, &peer
->sci
)) {
2410 secy_delete_receive_sc(kay
, rxsc
);
2411 ieee802_1x_kay_deinit_receive_sc(
2415 dl_list_del(&peer
->list
);
2422 if (dl_list_empty(&participant
->live_peers
)) {
2423 participant
->advised_desired
= FALSE
;
2424 participant
->advised_capability
=
2425 MACSEC_CAP_NOT_IMPLEMENTED
;
2426 participant
->to_use_sak
= FALSE
;
2427 kay
->authenticated
= TRUE
;
2428 kay
->secured
= FALSE
;
2429 kay
->failed
= FALSE
;
2438 dl_list_for_each_safe(txsa
, pre_txsa
,
2439 &participant
->txsc
->sa_list
,
2440 struct transmit_sa
, list
) {
2441 secy_disable_transmit_sa(kay
, txsa
);
2442 ieee802_1x_kay_deinit_transmit_sa(txsa
);
2445 ieee802_1x_cp_connect_authenticated(kay
->cp
);
2446 ieee802_1x_cp_sm_step(kay
->cp
);
2448 ieee802_1x_kay_elect_key_server(participant
);
2449 ieee802_1x_kay_decide_macsec_use(participant
);
2453 dl_list_for_each_safe(peer
, pre_peer
, &participant
->potential_peers
,
2454 struct ieee802_1x_kay_peer
, list
) {
2455 if (now
> peer
->expire
) {
2456 wpa_printf(MSG_DEBUG
, "KaY: Potential peer removed");
2457 wpa_hexdump(MSG_DEBUG
, "\tMI: ", peer
->mi
,
2459 wpa_printf(MSG_DEBUG
, "\tMN: %d", peer
->mn
);
2460 dl_list_del(&peer
->list
);
2465 if (participant
->new_sak
) {
2466 if (!ieee802_1x_kay_generate_new_sak(participant
))
2467 participant
->to_dist_sak
= TRUE
;
2469 participant
->new_sak
= FALSE
;
2472 if (participant
->retry_count
< MAX_RETRY_CNT
) {
2473 ieee802_1x_participant_send_mkpdu(participant
);
2474 participant
->retry_count
++;
2477 eloop_register_timeout(MKA_HELLO_TIME
/ 1000, 0,
2478 ieee802_1x_participant_timer
,
2484 * ieee802_1x_kay_init_transmit_sa -
2486 static struct transmit_sa
*
2487 ieee802_1x_kay_init_transmit_sa(struct transmit_sc
*psc
, u8 an
, u32 next_PN
,
2488 struct data_key
*key
)
2490 struct transmit_sa
*psa
;
2492 key
->tx_latest
= TRUE
;
2493 key
->rx_latest
= TRUE
;
2495 psa
= os_zalloc(sizeof(*psa
));
2497 wpa_printf(MSG_ERROR
, "%s: out of memory", __func__
);
2501 if (key
->confidentiality_offset
>= CONFIDENTIALITY_OFFSET_0
&&
2502 key
->confidentiality_offset
<= CONFIDENTIALITY_OFFSET_50
)
2503 psa
->confidentiality
= TRUE
;
2505 psa
->confidentiality
= FALSE
;
2509 psa
->next_pn
= next_PN
;
2512 os_get_time(&psa
->created_time
);
2513 psa
->in_use
= FALSE
;
2515 dl_list_add(&psc
->sa_list
, &psa
->list
);
2516 wpa_printf(MSG_DEBUG
,
2517 "KaY: Create transmit SA(an: %hhu, next_PN: %u) of SC(channel: %d)",
2518 an
, next_PN
, psc
->channel
);
2525 * ieee802_1x_kay_deinit_transmit_sa -
2527 static void ieee802_1x_kay_deinit_transmit_sa(struct transmit_sa
*psa
)
2530 wpa_printf(MSG_DEBUG
,
2531 "KaY: Delete transmit SA(an: %hhu) of SC",
2533 dl_list_del(&psa
->list
);
2539 * init_transmit_sc -
2541 static struct transmit_sc
*
2542 ieee802_1x_kay_init_transmit_sc(const struct ieee802_1x_mka_sci
*sci
,
2545 struct transmit_sc
*psc
;
2547 psc
= os_zalloc(sizeof(*psc
));
2549 wpa_printf(MSG_ERROR
, "%s: out of memory", __func__
);
2552 os_memcpy(&psc
->sci
, sci
, sizeof(psc
->sci
));
2553 psc
->channel
= channel
;
2555 os_get_time(&psc
->created_time
);
2556 psc
->transmitting
= FALSE
;
2557 psc
->encoding_sa
= FALSE
;
2558 psc
->enciphering_sa
= FALSE
;
2560 dl_list_init(&psc
->sa_list
);
2561 wpa_printf(MSG_DEBUG
, "KaY: Create transmit SC(channel: %d)", channel
);
2562 wpa_hexdump(MSG_DEBUG
, "SCI: ", (u8
*)sci
, sizeof(*sci
));
2569 * ieee802_1x_kay_deinit_transmit_sc -
2572 ieee802_1x_kay_deinit_transmit_sc(
2573 struct ieee802_1x_mka_participant
*participant
, struct transmit_sc
*psc
)
2575 struct transmit_sa
*psa
, *tmp
;
2577 wpa_printf(MSG_DEBUG
, "KaY: Delete transmit SC(channel: %d)",
2579 dl_list_for_each_safe(psa
, tmp
, &psc
->sa_list
, struct transmit_sa
,
2581 secy_disable_transmit_sa(participant
->kay
, psa
);
2582 ieee802_1x_kay_deinit_transmit_sa(psa
);
2589 /****************** Interface between CP and KAY *********************/
2591 * ieee802_1x_kay_set_latest_sa_attr -
2593 int ieee802_1x_kay_set_latest_sa_attr(struct ieee802_1x_kay
*kay
,
2594 struct ieee802_1x_mka_ki
*lki
, u8 lan
,
2595 Boolean ltx
, Boolean lrx
)
2597 struct ieee802_1x_mka_participant
*principal
;
2599 principal
= ieee802_1x_kay_get_principal_participant(kay
);
2604 os_memset(&principal
->lki
, 0, sizeof(principal
->lki
));
2606 os_memcpy(&principal
->lki
, lki
, sizeof(principal
->lki
));
2608 principal
->lan
= lan
;
2609 principal
->ltx
= ltx
;
2610 principal
->lrx
= lrx
;
2615 kay
->ltx_kn
= lki
->kn
;
2616 kay
->lrx_kn
= lki
->kn
;
2626 * ieee802_1x_kay_set_old_sa_attr -
2628 int ieee802_1x_kay_set_old_sa_attr(struct ieee802_1x_kay
*kay
,
2629 struct ieee802_1x_mka_ki
*oki
,
2630 u8 oan
, Boolean otx
, Boolean orx
)
2632 struct ieee802_1x_mka_participant
*principal
;
2634 principal
= ieee802_1x_kay_get_principal_participant(kay
);
2639 os_memset(&principal
->oki
, 0, sizeof(principal
->oki
));
2641 os_memcpy(&principal
->oki
, oki
, sizeof(principal
->oki
));
2643 principal
->oan
= oan
;
2644 principal
->otx
= otx
;
2645 principal
->orx
= orx
;
2651 kay
->otx_kn
= oki
->kn
;
2652 kay
->orx_kn
= oki
->kn
;
2662 * ieee802_1x_kay_create_sas -
2664 int ieee802_1x_kay_create_sas(struct ieee802_1x_kay
*kay
,
2665 struct ieee802_1x_mka_ki
*lki
)
2667 struct data_key
*sa_key
, *latest_sak
;
2668 struct ieee802_1x_mka_participant
*principal
;
2669 struct receive_sc
*rxsc
;
2670 struct receive_sa
*rxsa
;
2671 struct transmit_sa
*txsa
;
2673 principal
= ieee802_1x_kay_get_principal_participant(kay
);
2678 dl_list_for_each(sa_key
, &principal
->sak_list
, struct data_key
, list
) {
2679 if (is_ki_equal(&sa_key
->key_identifier
, lki
)) {
2680 sa_key
->rx_latest
= TRUE
;
2681 sa_key
->tx_latest
= TRUE
;
2682 latest_sak
= sa_key
;
2683 principal
->to_use_sak
= TRUE
;
2685 sa_key
->rx_latest
= FALSE
;
2686 sa_key
->tx_latest
= FALSE
;
2690 wpa_printf(MSG_ERROR
, "lki related sak not found");
2694 dl_list_for_each(rxsc
, &principal
->rxsc_list
, struct receive_sc
, list
) {
2695 rxsa
= ieee802_1x_kay_init_receive_sa(rxsc
, latest_sak
->an
, 1,
2700 secy_create_receive_sa(kay
, rxsa
);
2703 txsa
= ieee802_1x_kay_init_transmit_sa(principal
->txsc
, latest_sak
->an
,
2708 secy_create_transmit_sa(kay
, txsa
);
2717 * ieee802_1x_kay_delete_sas -
2719 int ieee802_1x_kay_delete_sas(struct ieee802_1x_kay
*kay
,
2720 struct ieee802_1x_mka_ki
*ki
)
2722 struct data_key
*sa_key
, *pre_key
;
2723 struct transmit_sa
*txsa
, *pre_txsa
;
2724 struct receive_sa
*rxsa
, *pre_rxsa
;
2725 struct receive_sc
*rxsc
;
2726 struct ieee802_1x_mka_participant
*principal
;
2728 wpa_printf(MSG_DEBUG
, "KaY: Entry into %s", __func__
);
2729 principal
= ieee802_1x_kay_get_principal_participant(kay
);
2733 /* remove the transmit sa */
2734 dl_list_for_each_safe(txsa
, pre_txsa
, &principal
->txsc
->sa_list
,
2735 struct transmit_sa
, list
) {
2736 if (is_ki_equal(&txsa
->pkey
->key_identifier
, ki
)) {
2737 secy_disable_transmit_sa(kay
, txsa
);
2738 ieee802_1x_kay_deinit_transmit_sa(txsa
);
2742 /* remove the receive sa */
2743 dl_list_for_each(rxsc
, &principal
->rxsc_list
, struct receive_sc
, list
) {
2744 dl_list_for_each_safe(rxsa
, pre_rxsa
, &rxsc
->sa_list
,
2745 struct receive_sa
, list
) {
2746 if (is_ki_equal(&rxsa
->pkey
->key_identifier
, ki
)) {
2747 secy_disable_receive_sa(kay
, rxsa
);
2748 ieee802_1x_kay_deinit_receive_sa(rxsa
);
2753 /* remove the sak */
2754 dl_list_for_each_safe(sa_key
, pre_key
, &principal
->sak_list
,
2755 struct data_key
, list
) {
2756 if (is_ki_equal(&sa_key
->key_identifier
, ki
)) {
2757 ieee802_1x_kay_deinit_data_key(sa_key
);
2760 if (principal
->new_key
== sa_key
)
2761 principal
->new_key
= NULL
;
2769 * ieee802_1x_kay_enable_tx_sas -
2771 int ieee802_1x_kay_enable_tx_sas(struct ieee802_1x_kay
*kay
,
2772 struct ieee802_1x_mka_ki
*lki
)
2774 struct ieee802_1x_mka_participant
*principal
;
2775 struct transmit_sa
*txsa
;
2777 principal
= ieee802_1x_kay_get_principal_participant(kay
);
2781 dl_list_for_each(txsa
, &principal
->txsc
->sa_list
, struct transmit_sa
,
2783 if (is_ki_equal(&txsa
->pkey
->key_identifier
, lki
)) {
2784 txsa
->in_use
= TRUE
;
2785 secy_enable_transmit_sa(kay
, txsa
);
2786 ieee802_1x_cp_set_usingtransmitas(
2787 principal
->kay
->cp
, TRUE
);
2788 ieee802_1x_cp_sm_step(principal
->kay
->cp
);
2797 * ieee802_1x_kay_enable_rx_sas -
2799 int ieee802_1x_kay_enable_rx_sas(struct ieee802_1x_kay
*kay
,
2800 struct ieee802_1x_mka_ki
*lki
)
2802 struct ieee802_1x_mka_participant
*principal
;
2803 struct receive_sa
*rxsa
;
2804 struct receive_sc
*rxsc
;
2806 principal
= ieee802_1x_kay_get_principal_participant(kay
);
2810 dl_list_for_each(rxsc
, &principal
->rxsc_list
, struct receive_sc
, list
) {
2811 dl_list_for_each(rxsa
, &rxsc
->sa_list
, struct receive_sa
, list
)
2813 if (is_ki_equal(&rxsa
->pkey
->key_identifier
, lki
)) {
2814 rxsa
->in_use
= TRUE
;
2815 secy_enable_receive_sa(kay
, rxsa
);
2816 ieee802_1x_cp_set_usingreceivesas(
2817 principal
->kay
->cp
, TRUE
);
2818 ieee802_1x_cp_sm_step(principal
->kay
->cp
);
2828 * ieee802_1x_kay_enable_new_info -
2830 int ieee802_1x_kay_enable_new_info(struct ieee802_1x_kay
*kay
)
2832 struct ieee802_1x_mka_participant
*principal
;
2834 principal
= ieee802_1x_kay_get_principal_participant(kay
);
2838 if (principal
->retry_count
< MAX_RETRY_CNT
) {
2839 ieee802_1x_participant_send_mkpdu(principal
);
2840 principal
->retry_count
++;
2848 * ieee802_1x_kay_cp_conf -
2850 int ieee802_1x_kay_cp_conf(struct ieee802_1x_kay
*kay
,
2851 struct ieee802_1x_cp_conf
*pconf
)
2853 pconf
->protect
= kay
->macsec_protect
;
2854 pconf
->replay_protect
= kay
->macsec_replay_protect
;
2855 pconf
->validate
= kay
->macsec_validate
;
2862 * ieee802_1x_kay_alloc_cp_sm -
2864 static struct ieee802_1x_cp_sm
*
2865 ieee802_1x_kay_alloc_cp_sm(struct ieee802_1x_kay
*kay
)
2867 struct ieee802_1x_cp_conf conf
;
2869 os_memset(&conf
, 0, sizeof(conf
));
2870 conf
.protect
= kay
->macsec_protect
;
2871 conf
.replay_protect
= kay
->macsec_replay_protect
;
2872 conf
.validate
= kay
->macsec_validate
;
2873 conf
.replay_window
= kay
->macsec_replay_window
;
2875 return ieee802_1x_cp_sm_init(kay
, &conf
);
2880 * ieee802_1x_kay_mkpdu_sanity_check -
2881 * sanity check specified in clause 11.11.2 of IEEE802.1X-2010
2883 static int ieee802_1x_kay_mkpdu_sanity_check(struct ieee802_1x_kay
*kay
,
2884 const u8
*buf
, size_t len
)
2886 struct ieee8023_hdr
*eth_hdr
;
2887 struct ieee802_1x_hdr
*eapol_hdr
;
2888 struct ieee802_1x_mka_hdr
*mka_hdr
;
2889 struct ieee802_1x_mka_basic_body
*body
;
2891 struct ieee802_1x_mka_participant
*participant
;
2893 u8 icv
[MAX_ICV_LEN
];
2896 eth_hdr
= (struct ieee8023_hdr
*) buf
;
2897 eapol_hdr
= (struct ieee802_1x_hdr
*) (eth_hdr
+ 1);
2898 mka_hdr
= (struct ieee802_1x_mka_hdr
*) (eapol_hdr
+ 1);
2900 /* destination address should be not individual address */
2901 if (os_memcmp(eth_hdr
->dest
, pae_group_addr
, ETH_ALEN
) != 0) {
2902 wpa_printf(MSG_MSGDUMP
,
2903 "KaY: ethernet destination address is not PAE group address");
2907 /* MKPDU should not less than 32 octets */
2908 mka_msg_len
= be_to_host16(eapol_hdr
->length
);
2909 if (mka_msg_len
< 32) {
2910 wpa_printf(MSG_MSGDUMP
, "KaY: MKPDU is less than 32 octets");
2913 /* MKPDU should multiple 4 octets */
2914 if ((mka_msg_len
% 4) != 0) {
2915 wpa_printf(MSG_MSGDUMP
,
2916 "KaY: MKPDU is not multiple of 4 octets");
2920 body
= (struct ieee802_1x_mka_basic_body
*) mka_hdr
;
2921 ieee802_1x_mka_dump_basic_body(body
);
2922 body_len
= get_mka_param_body_len(body
);
2923 /* EAPOL-MKA body should comprise basic parameter set and ICV */
2924 if (mka_msg_len
< MKA_HDR_LEN
+ body_len
+ DEFAULT_ICV_LEN
) {
2925 wpa_printf(MSG_ERROR
,
2926 "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",
2927 mka_msg_len
, MKA_HDR_LEN
,
2928 body_len
, DEFAULT_ICV_LEN
);
2932 /* CKN should be owned by I */
2933 participant
= ieee802_1x_kay_get_participant(kay
, body
->ckn
);
2935 wpa_printf(MSG_DEBUG
, "CKN is not included in my CA");
2939 /* algorithm agility check */
2940 if (os_memcmp(body
->algo_agility
, mka_algo_agility
,
2941 sizeof(body
->algo_agility
)) != 0) {
2942 wpa_printf(MSG_ERROR
,
2943 "KaY: peer's algorithm agility not supported for me");
2949 * The ICV will comprise the final octets of the packet body, whatever
2950 * its size, not the fixed length 16 octets, indicated by the EAPOL
2951 * packet body length.
2953 if (mka_alg_tbl
[kay
->mka_algindex
].icv_hash(
2954 participant
->ick
.key
,
2955 buf
, len
- mka_alg_tbl
[kay
->mka_algindex
].icv_len
, icv
)) {
2956 wpa_printf(MSG_ERROR
, "KaY: omac1_aes_128 failed");
2959 msg_icv
= ieee802_1x_mka_decode_icv_body(participant
, (u8
*) mka_hdr
,
2963 if (os_memcmp_const(msg_icv
, icv
,
2964 mka_alg_tbl
[kay
->mka_algindex
].icv_len
) !=
2966 wpa_printf(MSG_ERROR
,
2967 "KaY: Computed ICV is not equal to Received ICV");
2971 wpa_printf(MSG_ERROR
, "KaY: No ICV");
2980 * ieee802_1x_kay_decode_mkpdu -
2982 static int ieee802_1x_kay_decode_mkpdu(struct ieee802_1x_kay
*kay
,
2983 const u8
*buf
, size_t len
)
2985 struct ieee802_1x_mka_participant
*participant
;
2986 struct ieee802_1x_mka_hdr
*hdr
;
2992 Boolean my_included
;
2993 Boolean handled
[256];
2995 if (ieee802_1x_kay_mkpdu_sanity_check(kay
, buf
, len
))
2998 /* handle basic parameter set */
2999 pos
= buf
+ sizeof(struct ieee8023_hdr
) + sizeof(struct ieee802_1x_hdr
);
3000 left_len
= len
- sizeof(struct ieee8023_hdr
) -
3001 sizeof(struct ieee802_1x_hdr
);
3002 participant
= ieee802_1x_mka_decode_basic_body(kay
, pos
, left_len
);
3006 /* to skip basic parameter set */
3007 hdr
= (struct ieee802_1x_mka_hdr
*) pos
;
3008 body_len
= get_mka_param_body_len(hdr
);
3009 pos
+= body_len
+ MKA_HDR_LEN
;
3010 left_len
-= body_len
+ MKA_HDR_LEN
;
3012 /* check i am in the peer's peer list */
3013 my_included
= ieee802_1x_mka_i_in_peerlist(participant
, pos
, left_len
);
3015 /* accept the peer as live peer */
3016 if (!ieee802_1x_kay_is_in_peer(
3018 participant
->current_peer_id
.mi
)) {
3019 if (!ieee802_1x_kay_create_live_peer(
3021 participant
->current_peer_id
.mi
,
3023 participant
->current_peer_id
.mn
)))
3025 ieee802_1x_kay_elect_key_server(participant
);
3026 ieee802_1x_kay_decide_macsec_use(participant
);
3028 if (ieee802_1x_kay_is_in_potential_peer(
3029 participant
, participant
->current_peer_id
.mi
)) {
3030 if (!ieee802_1x_kay_move_live_peer(
3032 participant
->current_peer_id
.mi
,
3033 be_to_host32(participant
->
3034 current_peer_id
.mn
)))
3036 ieee802_1x_kay_elect_key_server(participant
);
3037 ieee802_1x_kay_decide_macsec_use(participant
);
3042 * Handle other parameter set than basic parameter set.
3043 * Each parameter set should be present only once.
3045 for (i
= 0; i
< 256; i
++)
3049 for (; left_len
> MKA_HDR_LEN
+ DEFAULT_ICV_LEN
;
3050 pos
+= body_len
+ MKA_HDR_LEN
,
3051 left_len
-= body_len
+ MKA_HDR_LEN
) {
3052 hdr
= (struct ieee802_1x_mka_hdr
*) pos
;
3053 body_len
= get_mka_param_body_len(hdr
);
3054 body_type
= get_mka_param_body_type(hdr
);
3056 if (body_type
== MKA_ICV_INDICATOR
)
3059 if (left_len
< (MKA_HDR_LEN
+ body_len
+ DEFAULT_ICV_LEN
)) {
3060 wpa_printf(MSG_ERROR
,
3061 "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",
3062 left_len
, MKA_HDR_LEN
,
3063 body_len
, DEFAULT_ICV_LEN
);
3067 if (handled
[body_type
])
3070 handled
[body_type
] = TRUE
;
3071 if (body_type
< ARRAY_SIZE(mka_body_handler
) &&
3072 mka_body_handler
[body_type
].body_rx
) {
3073 mka_body_handler
[body_type
].body_rx
3074 (participant
, pos
, left_len
);
3076 wpa_printf(MSG_ERROR
,
3077 "The type %d is not supported in this MKA version %d",
3078 body_type
, MKA_VERSION_ID
);
3083 participant
->retry_count
= 0;
3084 participant
->active
= TRUE
;
3091 static void kay_l2_receive(void *ctx
, const u8
*src_addr
, const u8
*buf
,
3094 struct ieee802_1x_kay
*kay
= ctx
;
3095 struct ieee8023_hdr
*eth_hdr
;
3096 struct ieee802_1x_hdr
*eapol_hdr
;
3098 /* must contain at least ieee8023_hdr + ieee802_1x_hdr */
3099 if (len
< sizeof(*eth_hdr
) + sizeof(*eapol_hdr
)) {
3100 wpa_printf(MSG_MSGDUMP
, "KaY: EAPOL frame too short (%lu)",
3101 (unsigned long) len
);
3105 eth_hdr
= (struct ieee8023_hdr
*) buf
;
3106 eapol_hdr
= (struct ieee802_1x_hdr
*) (eth_hdr
+ 1);
3107 if (len
!= sizeof(*eth_hdr
) + sizeof(*eapol_hdr
) +
3108 be_to_host16(eapol_hdr
->length
)) {
3109 wpa_printf(MSG_MSGDUMP
, "KAY: EAPOL MPDU is invalid: (%lu-%lu)",
3110 (unsigned long) len
,
3111 (unsigned long) be_to_host16(eapol_hdr
->length
));
3115 if (eapol_hdr
->version
< EAPOL_VERSION
) {
3116 wpa_printf(MSG_MSGDUMP
, "KaY: version %d does not support MKA",
3117 eapol_hdr
->version
);
3120 if (be_to_host16(eth_hdr
->ethertype
) != ETH_P_PAE
||
3121 eapol_hdr
->type
!= IEEE802_1X_TYPE_EAPOL_MKA
)
3124 wpa_hexdump(MSG_DEBUG
, "RX EAPOL-MKA: ", buf
, len
);
3125 if (dl_list_empty(&kay
->participant_list
)) {
3126 wpa_printf(MSG_ERROR
, "KaY: no MKA participant instance");
3130 ieee802_1x_kay_decode_mkpdu(kay
, buf
, len
);
3135 * ieee802_1x_kay_init -
3137 struct ieee802_1x_kay
*
3138 ieee802_1x_kay_init(struct ieee802_1x_kay_ctx
*ctx
, enum macsec_policy policy
,
3139 const char *ifname
, const u8
*addr
)
3141 struct ieee802_1x_kay
*kay
;
3143 kay
= os_zalloc(sizeof(*kay
));
3145 wpa_printf(MSG_ERROR
, "KaY-%s: out of memory", __func__
);
3152 kay
->active
= FALSE
;
3154 kay
->authenticated
= FALSE
;
3155 kay
->secured
= FALSE
;
3156 kay
->failed
= FALSE
;
3157 kay
->policy
= policy
;
3159 os_strlcpy(kay
->if_name
, ifname
, IFNAMSIZ
);
3160 os_memcpy(kay
->actor_sci
.addr
, addr
, ETH_ALEN
);
3161 kay
->actor_sci
.port
= host_to_be16(0x0001);
3162 kay
->actor_priority
= DEFAULT_PRIO_NOT_KEY_SERVER
;
3164 /* While actor acts as a key server, shall distribute sakey */
3169 kay
->pn_exhaustion
= PENDING_PN_EXHAUSTION
;
3170 kay
->macsec_csindex
= DEFAULT_CS_INDEX
;
3171 kay
->mka_algindex
= DEFAULT_MKA_ALG_INDEX
;
3172 kay
->mka_version
= MKA_VERSION_ID
;
3174 os_memcpy(kay
->algo_agility
, mka_algo_agility
,
3175 sizeof(kay
->algo_agility
));
3177 dl_list_init(&kay
->participant_list
);
3179 if (policy
== DO_NOT_SECURE
) {
3180 kay
->macsec_capable
= MACSEC_CAP_NOT_IMPLEMENTED
;
3181 kay
->macsec_desired
= FALSE
;
3182 kay
->macsec_protect
= FALSE
;
3183 kay
->macsec_validate
= Disabled
;
3184 kay
->macsec_replay_protect
= FALSE
;
3185 kay
->macsec_replay_window
= 0;
3186 kay
->macsec_confidentiality
= CONFIDENTIALITY_NONE
;
3188 kay
->macsec_capable
= MACSEC_CAP_INTEG_AND_CONF_0_30_50
;
3189 kay
->macsec_desired
= TRUE
;
3190 kay
->macsec_protect
= TRUE
;
3191 kay
->macsec_validate
= Strict
;
3192 kay
->macsec_replay_protect
= FALSE
;
3193 kay
->macsec_replay_window
= 0;
3194 kay
->macsec_confidentiality
= CONFIDENTIALITY_OFFSET_0
;
3197 wpa_printf(MSG_DEBUG
, "KaY: state machine created");
3199 /* Initialize the SecY must be prio to CP, as CP will control SecY */
3200 secy_init_macsec(kay
);
3201 secy_get_available_transmit_sc(kay
, &kay
->sc_ch
);
3203 wpa_printf(MSG_DEBUG
, "KaY: secy init macsec done");
3206 kay
->cp
= ieee802_1x_kay_alloc_cp_sm(kay
);
3207 if (kay
->cp
== NULL
) {
3208 ieee802_1x_kay_deinit(kay
);
3212 if (policy
== DO_NOT_SECURE
) {
3213 ieee802_1x_cp_connect_authenticated(kay
->cp
);
3214 ieee802_1x_cp_sm_step(kay
->cp
);
3216 kay
->l2_mka
= l2_packet_init(kay
->if_name
, NULL
, ETH_P_PAE
,
3217 kay_l2_receive
, kay
, 1);
3218 if (kay
->l2_mka
== NULL
) {
3219 wpa_printf(MSG_WARNING
,
3220 "KaY: Failed to initialize L2 packet processing for MKA packet");
3221 ieee802_1x_kay_deinit(kay
);
3231 * ieee802_1x_kay_deinit -
3234 ieee802_1x_kay_deinit(struct ieee802_1x_kay
*kay
)
3236 struct ieee802_1x_mka_participant
*participant
;
3241 wpa_printf(MSG_DEBUG
, "KaY: state machine removed");
3243 while (!dl_list_empty(&kay
->participant_list
)) {
3244 participant
= dl_list_entry(kay
->participant_list
.next
,
3245 struct ieee802_1x_mka_participant
,
3247 ieee802_1x_kay_delete_mka(kay
, &participant
->ckn
);
3250 ieee802_1x_cp_sm_deinit(kay
->cp
);
3251 secy_deinit_macsec(kay
);
3254 l2_packet_deinit(kay
->l2_mka
);
3264 * ieee802_1x_kay_create_mka -
3266 struct ieee802_1x_mka_participant
*
3267 ieee802_1x_kay_create_mka(struct ieee802_1x_kay
*kay
, struct mka_key_name
*ckn
,
3268 struct mka_key
*cak
, u32 life
,
3269 enum mka_created_mode mode
, Boolean is_authenticator
)
3271 struct ieee802_1x_mka_participant
*participant
;
3274 if (!kay
|| !ckn
|| !cak
) {
3275 wpa_printf(MSG_ERROR
, "KaY: ckn or cak is null");
3279 if (cak
->len
!= mka_alg_tbl
[kay
->mka_algindex
].cak_len
) {
3280 wpa_printf(MSG_ERROR
, "KaY: CAK length not follow key schema");
3283 if (ckn
->len
> MAX_CKN_LEN
) {
3284 wpa_printf(MSG_ERROR
, "KaY: CKN is out of range(<=32 bytes)");
3288 wpa_printf(MSG_ERROR
, "KaY: Now is at disable state");
3292 participant
= os_zalloc(sizeof(*participant
));
3294 wpa_printf(MSG_ERROR
, "KaY-%s: out of memory", __func__
);
3298 participant
->ckn
.len
= ckn
->len
;
3299 os_memcpy(participant
->ckn
.name
, ckn
->name
, ckn
->len
);
3300 participant
->cak
.len
= cak
->len
;
3301 os_memcpy(participant
->cak
.key
, cak
->key
, cak
->len
);
3303 participant
->cak_life
= life
+ time(NULL
);
3307 if (is_authenticator
) {
3308 participant
->is_obliged_key_server
= TRUE
;
3309 participant
->can_be_key_server
= TRUE
;
3310 participant
->is_key_server
= TRUE
;
3311 participant
->principal
= TRUE
;
3313 os_memcpy(&kay
->key_server_sci
, &kay
->actor_sci
,
3314 sizeof(kay
->key_server_sci
));
3315 kay
->key_server_priority
= kay
->actor_priority
;
3316 participant
->is_elected
= TRUE
;
3318 participant
->is_obliged_key_server
= FALSE
;
3319 participant
->can_be_key_server
= FALSE
;
3320 participant
->is_key_server
= FALSE
;
3321 participant
->is_elected
= TRUE
;
3326 participant
->is_obliged_key_server
= FALSE
;
3327 participant
->can_be_key_server
= TRUE
;
3328 participant
->is_key_server
= TRUE
;
3329 participant
->is_elected
= FALSE
;
3333 participant
->cached
= FALSE
;
3335 participant
->active
= FALSE
;
3336 participant
->participant
= FALSE
;
3337 participant
->retain
= FALSE
;
3338 participant
->activate
= DEFAULT
;
3340 if (participant
->is_key_server
)
3341 participant
->principal
= TRUE
;
3343 dl_list_init(&participant
->live_peers
);
3344 dl_list_init(&participant
->potential_peers
);
3346 participant
->retry_count
= 0;
3347 participant
->kay
= kay
;
3349 if (!reset_participant_mi(participant
))
3352 participant
->lrx
= FALSE
;
3353 participant
->ltx
= FALSE
;
3354 participant
->orx
= FALSE
;
3355 participant
->otx
= FALSE
;
3356 participant
->to_dist_sak
= FALSE
;
3357 participant
->to_use_sak
= FALSE
;
3358 participant
->new_sak
= FALSE
;
3359 dl_list_init(&participant
->sak_list
);
3360 participant
->new_key
= NULL
;
3361 dl_list_init(&participant
->rxsc_list
);
3362 participant
->txsc
= ieee802_1x_kay_init_transmit_sc(&kay
->actor_sci
,
3364 secy_cp_control_protect_frames(kay
, kay
->macsec_protect
);
3365 secy_cp_control_replay(kay
, kay
->macsec_replay_protect
,
3366 kay
->macsec_replay_window
);
3367 secy_create_transmit_sc(kay
, participant
->txsc
);
3369 /* to derive KEK from CAK and CKN */
3370 participant
->kek
.len
= mka_alg_tbl
[kay
->mka_algindex
].kek_len
;
3371 if (mka_alg_tbl
[kay
->mka_algindex
].kek_trfm(participant
->cak
.key
,
3372 participant
->ckn
.name
,
3373 participant
->ckn
.len
,
3374 participant
->kek
.key
)) {
3375 wpa_printf(MSG_ERROR
, "KaY: Derived KEK failed");
3378 wpa_hexdump_key(MSG_DEBUG
, "KaY: Derived KEK",
3379 participant
->kek
.key
, participant
->kek
.len
);
3381 /* to derive ICK from CAK and CKN */
3382 participant
->ick
.len
= mka_alg_tbl
[kay
->mka_algindex
].ick_len
;
3383 if (mka_alg_tbl
[kay
->mka_algindex
].ick_trfm(participant
->cak
.key
,
3384 participant
->ckn
.name
,
3385 participant
->ckn
.len
,
3386 participant
->ick
.key
)) {
3387 wpa_printf(MSG_ERROR
, "KaY: Derived ICK failed");
3390 wpa_hexdump_key(MSG_DEBUG
, "KaY: Derived ICK",
3391 participant
->ick
.key
, participant
->ick
.len
);
3393 dl_list_add(&kay
->participant_list
, &participant
->list
);
3394 wpa_hexdump(MSG_DEBUG
, "KaY: Participant created:",
3395 ckn
->name
, ckn
->len
);
3397 usecs
= os_random() % (MKA_HELLO_TIME
* 1000);
3398 eloop_register_timeout(0, usecs
, ieee802_1x_participant_timer
,
3400 participant
->mka_life
= MKA_LIFE_TIME
/ 1000 + time(NULL
) +
3406 os_free(participant
);
3412 * ieee802_1x_kay_delete_mka -
3415 ieee802_1x_kay_delete_mka(struct ieee802_1x_kay
*kay
, struct mka_key_name
*ckn
)
3417 struct ieee802_1x_mka_participant
*participant
;
3418 struct ieee802_1x_kay_peer
*peer
;
3419 struct data_key
*sak
;
3420 struct receive_sc
*rxsc
;
3425 wpa_printf(MSG_DEBUG
, "KaY: participant removed");
3427 /* get the participant */
3428 participant
= ieee802_1x_kay_get_participant(kay
, ckn
->name
);
3430 wpa_hexdump(MSG_DEBUG
, "KaY: participant is not found",
3431 ckn
->name
, ckn
->len
);
3435 eloop_cancel_timeout(ieee802_1x_participant_timer
, participant
, NULL
);
3436 dl_list_del(&participant
->list
);
3438 /* remove live peer */
3439 while (!dl_list_empty(&participant
->live_peers
)) {
3440 peer
= dl_list_entry(participant
->live_peers
.next
,
3441 struct ieee802_1x_kay_peer
, list
);
3442 dl_list_del(&peer
->list
);
3446 /* remove potential peer */
3447 while (!dl_list_empty(&participant
->potential_peers
)) {
3448 peer
= dl_list_entry(participant
->potential_peers
.next
,
3449 struct ieee802_1x_kay_peer
, list
);
3450 dl_list_del(&peer
->list
);
3455 while (!dl_list_empty(&participant
->sak_list
)) {
3456 sak
= dl_list_entry(participant
->sak_list
.next
,
3457 struct data_key
, list
);
3458 dl_list_del(&sak
->list
);
3462 while (!dl_list_empty(&participant
->rxsc_list
)) {
3463 rxsc
= dl_list_entry(participant
->rxsc_list
.next
,
3464 struct receive_sc
, list
);
3465 secy_delete_receive_sc(kay
, rxsc
);
3466 ieee802_1x_kay_deinit_receive_sc(participant
, rxsc
);
3468 secy_delete_transmit_sc(kay
, participant
->txsc
);
3469 ieee802_1x_kay_deinit_transmit_sc(participant
, participant
->txsc
);
3471 os_memset(&participant
->cak
, 0, sizeof(participant
->cak
));
3472 os_memset(&participant
->kek
, 0, sizeof(participant
->kek
));
3473 os_memset(&participant
->ick
, 0, sizeof(participant
->ick
));
3474 os_free(participant
);
3479 * ieee802_1x_kay_mka_participate -
3481 void ieee802_1x_kay_mka_participate(struct ieee802_1x_kay
*kay
,
3482 struct mka_key_name
*ckn
,
3485 struct ieee802_1x_mka_participant
*participant
;
3490 participant
= ieee802_1x_kay_get_participant(kay
, ckn
->name
);
3494 participant
->active
= status
;
3499 * ieee802_1x_kay_new_sak -
3502 ieee802_1x_kay_new_sak(struct ieee802_1x_kay
*kay
)
3504 struct ieee802_1x_mka_participant
*participant
;
3509 participant
= ieee802_1x_kay_get_principal_participant(kay
);
3513 participant
->new_sak
= TRUE
;
3514 wpa_printf(MSG_DEBUG
, "KaY: new SAK signal");
3521 * ieee802_1x_kay_change_cipher_suite -
3524 ieee802_1x_kay_change_cipher_suite(struct ieee802_1x_kay
*kay
, int cs_index
)
3526 struct ieee802_1x_mka_participant
*participant
;
3531 if ((unsigned int) cs_index
>= CS_TABLE_SIZE
) {
3532 wpa_printf(MSG_ERROR
,
3533 "KaY: Configured cipher suite index is out of range");
3536 if (kay
->macsec_csindex
== cs_index
)
3540 kay
->macsec_desired
= FALSE
;
3542 kay
->macsec_csindex
= cs_index
;
3543 kay
->macsec_capable
= cipher_suite_tbl
[kay
->macsec_csindex
].capable
;
3545 participant
= ieee802_1x_kay_get_principal_participant(kay
);
3547 wpa_printf(MSG_INFO
, "KaY: Cipher Suite changed");
3548 participant
->new_sak
= TRUE
;