#define PENDING_PN_EXHAUSTION 0xC0000000
+#define MKA_ALIGN_LENGTH(len) (((len) + 0x3) & ~0x3)
+
/* IEEE Std 802.1X-2010, Table 9-1 - MKA Algorithm Agility */
#define MKA_ALGO_AGILITY_2009 { 0x00, 0x80, 0xC2, 0x01 }
static u8 mka_algo_agility[4] = MKA_ALGO_AGILITY_2009;
static struct macsec_ciphersuite cipher_suite_tbl[] = {
/* GCM-AES-128 */
{
- CS_ID_GCM_AES_128,
- CS_NAME_GCM_AES_128,
- MACSEC_CAP_INTEG_AND_CONF_0_30_50,
- 16,
-
- 0 /* index */
+ .id = CS_ID_GCM_AES_128,
+ .name = CS_NAME_GCM_AES_128,
+ .capable = MACSEC_CAP_INTEG_AND_CONF_0_30_50,
+ .sak_len = DEFAULT_SA_KEY_LEN,
+ .index = 0,
},
};
#define CS_TABLE_SIZE (ARRAY_SIZE(cipher_suite_tbl))
static struct mka_alg mka_alg_tbl[] = {
{
- MKA_ALGO_AGILITY_2009,
+ .parameter = MKA_ALGO_AGILITY_2009,
+
/* 128-bit CAK, KEK, ICK, ICV */
- 16, 16, 16, 16,
- ieee802_1x_cak_128bits_aes_cmac,
- ieee802_1x_ckn_128bits_aes_cmac,
- ieee802_1x_kek_128bits_aes_cmac,
- ieee802_1x_ick_128bits_aes_cmac,
- ieee802_1x_icv_128bits_aes_cmac,
-
- 1, /* index */
+ .cak_len = DEFAULT_ICV_LEN,
+ .kek_len = DEFAULT_ICV_LEN,
+ .ick_len = DEFAULT_ICV_LEN,
+ .icv_len = DEFAULT_ICV_LEN,
+
+ .cak_trfm = ieee802_1x_cak_128bits_aes_cmac,
+ .ckn_trfm = ieee802_1x_ckn_128bits_aes_cmac,
+ .kek_trfm = ieee802_1x_kek_128bits_aes_cmac,
+ .ick_trfm = ieee802_1x_ick_128bits_aes_cmac,
+ .icv_hash = ieee802_1x_icv_128bits_aes_cmac,
+
+ .index = 1,
},
};
#define MKA_ALG_TABLE_SIZE (ARRAY_SIZE(mka_alg_tbl))
wpa_printf(MSG_DEBUG, "\tKeySvr........: %d", body->key_server);
wpa_printf(MSG_DEBUG, "\tMACSecDesired.: %d", body->macsec_desired);
wpa_printf(MSG_DEBUG, "\tMACSecCapable.: %d", body->macsec_capability);
- wpa_printf(MSG_DEBUG, "\tBody Length...: %d", (int) body_len);
+ wpa_printf(MSG_DEBUG, "\tBody Length...: %zu", body_len);
wpa_printf(MSG_DEBUG, "\tSCI MAC.......: " MACSTR,
MAC2STR(body->actor_sci.addr));
wpa_printf(MSG_DEBUG, "\tSCI Port .....: %d",
body_len = get_mka_param_body_len(body);
if (body->type == MKA_LIVE_PEER_LIST) {
wpa_printf(MSG_DEBUG, "*** Live Peer List ***");
- wpa_printf(MSG_DEBUG, "\tBody Length...: %d", (int) body_len);
+ wpa_printf(MSG_DEBUG, "\tBody Length...: %zu", body_len);
} else if (body->type == MKA_POTENTIAL_PEER_LIST) {
wpa_printf(MSG_DEBUG, "*** Potential Live Peer List ***");
- wpa_printf(MSG_DEBUG, "\tBody Length...: %d", (int) body_len);
+ wpa_printf(MSG_DEBUG, "\tBody Length...: %zu", body_len);
}
for (i = 0; i < body_len; i += MI_LEN + sizeof(mn)) {
wpa_printf(MSG_INFO, "\tDistributed AN........: %d", body->dan);
wpa_printf(MSG_INFO, "\tConfidentiality Offset: %d",
body->confid_offset);
- wpa_printf(MSG_INFO, "\tBody Length...........: %d", (int) body_len);
+ wpa_printf(MSG_INFO, "\tBody Length...........: %zu", body_len);
if (!body_len)
return;
/**
+ * ieee802_1x_kay_get_potential_peer
+ */
+static struct ieee802_1x_kay_peer *
+ieee802_1x_kay_get_potential_peer(
+ struct ieee802_1x_mka_participant *participant, const u8 *mi)
+{
+ return get_peer_mi(&participant->potential_peers, mi);
+}
+
+
+/**
+ * ieee802_1x_kay_get_live_peer
+ */
+static struct ieee802_1x_kay_peer *
+ieee802_1x_kay_get_live_peer(struct ieee802_1x_mka_participant *participant,
+ const u8 *mi)
+{
+ return get_peer_mi(&participant->live_peers, mi);
+}
+
+
+/**
* ieee802_1x_kay_is_in_potential_peer
*/
static Boolean
ieee802_1x_kay_is_in_potential_peer(
struct ieee802_1x_mka_participant *participant, const u8 *mi)
{
- return get_peer_mi(&participant->potential_peers, mi) != NULL;
+ return ieee802_1x_kay_get_potential_peer(participant, mi) != NULL;
}
ieee802_1x_kay_is_in_live_peer(
struct ieee802_1x_mka_participant *participant, const u8 *mi)
{
- return get_peer_mi(&participant->live_peers, mi) != NULL;
+ return ieee802_1x_kay_get_live_peer(participant, mi) != NULL;
}
{
struct ieee802_1x_kay_peer *peer;
- peer = get_peer_mi(&participant->live_peers, mi);
+ peer = ieee802_1x_kay_get_live_peer(participant, mi);
if (peer)
return peer;
- return get_peer_mi(&participant->potential_peers, mi);
-}
-
-
-/**
- * ieee802_1x_kay_get_live_peer
- */
-static struct ieee802_1x_kay_peer *
-ieee802_1x_kay_get_live_peer(struct ieee802_1x_mka_participant *participant,
- const u8 *mi)
-{
- return get_peer_mi(&participant->live_peers, mi);
+ return ieee802_1x_kay_get_potential_peer(participant, mi);
}
for (i = 0; i < CS_TABLE_SIZE; i++) {
if (os_memcmp(cipher_suite_tbl[i].id, cs_id, CS_ID_LEN) == 0)
- break;
+ return &cipher_suite_tbl[i];
}
- if (i >= CS_TABLE_SIZE)
- return NULL;
- return &cipher_suite_tbl[i];
+ return NULL;
}
dl_list_add(&psc->sa_list, &psa->list);
wpa_printf(MSG_DEBUG,
- "KaY: Create receive SA(AN: %d lowest_pn: %u of SC(channel: %d)",
- (int) an, lowest_pn, psc->channel);
+ "KaY: Create receive SA(AN: %hhu lowest_pn: %u of SC(channel: %d)",
+ an, lowest_pn, psc->channel);
return psa;
}
{
psa->pkey = NULL;
wpa_printf(MSG_DEBUG,
- "KaY: Delete receive SA(an: %d) of SC(channel: %d)",
- psa->an, psa->sc->channel);
+ "KaY: Delete receive SA(an: %hhu) of SC",
+ psa->an);
dl_list_del(&psa->list);
os_free(psa);
}
}
-/**
- * ieee802_1x_kay_create_live_peer
- */
+static void ieee802_1x_kay_dump_peer(struct ieee802_1x_kay_peer *peer)
+{
+ wpa_hexdump(MSG_DEBUG, "\tMI: ", peer->mi, sizeof(peer->mi));
+ wpa_printf(MSG_DEBUG, "\tMN: %d", peer->mn);
+ wpa_hexdump(MSG_DEBUG, "\tSCI Addr: ", peer->sci.addr, ETH_ALEN);
+ wpa_printf(MSG_DEBUG, "\tPort: %d", peer->sci.port);
+}
+
+
static struct ieee802_1x_kay_peer *
-ieee802_1x_kay_create_live_peer(struct ieee802_1x_mka_participant *participant,
- u8 *mi, u32 mn)
+ieee802_1x_kay_create_peer(const u8 *mi, u32 mn)
{
struct ieee802_1x_kay_peer *peer;
- struct receive_sc *rxsc;
- u32 sc_ch = 0;
peer = os_zalloc(sizeof(*peer));
- if (peer == NULL) {
+ if (!peer) {
wpa_printf(MSG_ERROR, "KaY-%s: out of memory", __func__);
return NULL;
}
peer->mn = mn;
peer->expire = time(NULL) + MKA_LIFE_TIME / 1000;
peer->sak_used = FALSE;
+
+ return peer;
+}
+
+
+/**
+ * ieee802_1x_kay_create_live_peer
+ */
+static struct ieee802_1x_kay_peer *
+ieee802_1x_kay_create_live_peer(struct ieee802_1x_mka_participant *participant,
+ const u8 *mi, u32 mn)
+{
+ struct ieee802_1x_kay_peer *peer;
+ struct receive_sc *rxsc;
+ u32 sc_ch = 0;
+
+ peer = ieee802_1x_kay_create_peer(mi, mn);
+ if (!peer)
+ return NULL;
+
os_memcpy(&peer->sci, &participant->current_peer_sci,
sizeof(peer->sci));
secy_create_receive_sc(participant->kay, rxsc);
wpa_printf(MSG_DEBUG, "KaY: Live peer created");
- wpa_hexdump(MSG_DEBUG, "\tMI: ", peer->mi, sizeof(peer->mi));
- wpa_printf(MSG_DEBUG, "\tMN: %d", peer->mn);
- wpa_hexdump(MSG_DEBUG, "\tSCI Addr: ", peer->sci.addr, ETH_ALEN);
- wpa_printf(MSG_DEBUG, "\tPort: %d", peer->sci.port);
+ ieee802_1x_kay_dump_peer(peer);
return peer;
}
{
struct ieee802_1x_kay_peer *peer;
- peer = os_zalloc(sizeof(*peer));
- if (peer == NULL) {
- wpa_printf(MSG_ERROR, "KaY-%s: out of memory", __func__);
+ peer = ieee802_1x_kay_create_peer(mi, mn);
+ if (!peer)
return NULL;
- }
-
- os_memcpy(peer->mi, mi, MI_LEN);
- peer->mn = mn;
- peer->expire = time(NULL) + MKA_LIFE_TIME / 1000;
- peer->sak_used = FALSE;
dl_list_add(&participant->potential_peers, &peer->list);
wpa_printf(MSG_DEBUG, "KaY: potential peer created");
- wpa_hexdump(MSG_DEBUG, "\tMI: ", peer->mi, sizeof(peer->mi));
- wpa_printf(MSG_DEBUG, "\tMN: %d", peer->mn);
- wpa_hexdump(MSG_DEBUG, "\tSCI Addr: ", peer->sci.addr, ETH_ALEN);
- wpa_printf(MSG_DEBUG, "\tPort: %d", peer->sci.port);
+ ieee802_1x_kay_dump_peer(peer);
return peer;
}
struct receive_sc *rxsc;
u32 sc_ch = 0;
- dl_list_for_each(peer, &participant->potential_peers,
- struct ieee802_1x_kay_peer, list) {
- if (os_memcmp(peer->mi, mi, MI_LEN) == 0)
- break;
- }
+ peer = ieee802_1x_kay_get_potential_peer(participant, mi);
rxsc = ieee802_1x_kay_init_receive_sc(&participant->current_peer_sci,
sc_ch);
peer->expire = time(NULL) + MKA_LIFE_TIME / 1000;
wpa_printf(MSG_DEBUG, "KaY: move potential peer to live peer");
- wpa_hexdump(MSG_DEBUG, "\tMI: ", peer->mi, sizeof(peer->mi));
- wpa_printf(MSG_DEBUG, "\tMN: %d", peer->mn);
- wpa_hexdump(MSG_DEBUG, "\tSCI Addr: ", peer->sci.addr, ETH_ALEN);
- wpa_printf(MSG_DEBUG, "\tPort: %d", peer->sci.port);
+ ieee802_1x_kay_dump_peer(peer);
dl_list_del(&peer->list);
dl_list_add_tail(&participant->live_peers, &peer->list);
length = sizeof(struct ieee802_1x_mka_basic_body);
length += participant->ckn.len;
- return (length + 0x3) & ~0x3;
+ return MKA_ALIGN_LENGTH(length);
}
struct ieee802_1x_kay_peer, list)
len += sizeof(struct ieee802_1x_mka_peer_id);
- return (len + 0x3) & ~0x3;
+ return MKA_ALIGN_LENGTH(len);
}
struct ieee802_1x_kay_peer, list)
len += sizeof(struct ieee802_1x_mka_peer_id);
- return (len + 0x3) & ~0x3;
+ return MKA_ALIGN_LENGTH(len);
}
if (left_len < (MKA_HDR_LEN + body_len + DEFAULT_ICV_LEN)) {
wpa_printf(MSG_ERROR,
- "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",
- (int) left_len, (int) MKA_HDR_LEN,
- (int) body_len, DEFAULT_ICV_LEN);
+ "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",
+ left_len, MKA_HDR_LEN,
+ body_len, DEFAULT_ICV_LEN);
goto SKIP_PEER;
}
if ((body_len % 16) != 0) {
wpa_printf(MSG_ERROR,
- "KaY: MKA Peer Packet Body Length (%d bytes) should multiple of 16 octets",
- (int) body_len);
+ "KaY: MKA Peer Packet Body Length (%zu bytes) should be a multiple of 16 octets",
+ body_len);
goto SKIP_PEER;
}
if (participant->kay->macsec_desired && participant->advised_desired)
length = sizeof(struct ieee802_1x_mka_sak_use_body);
- else
- length = MKA_HDR_LEN;
-
- length = (length + 0x3) & ~0x3;
- return length;
+ return MKA_ALIGN_LENGTH(length);
}
if ((body_len != 0) && (body_len < 40)) {
wpa_printf(MSG_ERROR,
- "KaY: MKA Use SAK Packet Body Length (%d bytes) should be 0, 40, or more octets",
- (int) body_len);
+ "KaY: MKA Use SAK Packet Body Length (%zu bytes) should be 0, 40, or more octets",
+ body_len);
return -1;
}
ieee802_1x_mka_get_dist_sak_length(
struct ieee802_1x_mka_participant *participant)
{
- int length;
+ int length = MKA_HDR_LEN;
int cs_index = participant->kay->macsec_csindex;
if (participant->advised_desired) {
length += CS_ID_LEN;
length += cipher_suite_tbl[cs_index].sak_len + 8;
- } else {
- length = MKA_HDR_LEN;
}
- length = (length + 0x3) & ~0x3;
- return length;
+ return MKA_ALIGN_LENGTH(length);
}
body_len = get_mka_param_body_len(hdr);
if ((body_len != 0) && (body_len != 28) && (body_len < 36)) {
wpa_printf(MSG_ERROR,
- "KaY: MKA Use SAK Packet Body Length (%d bytes) should be 0, 28, 36, or more octets",
- (int) body_len);
+ "KaY: MKA Use SAK Packet Body Length (%zu bytes) should be 0, 28, 36, or more octets",
+ body_len);
return -1;
}
length = sizeof(struct ieee802_1x_mka_icv_body);
length += mka_alg_tbl[participant->kay->mka_algindex].icv_len;
- return (length + 0x3) & ~0x3;
+ return MKA_ALIGN_LENGTH(length);
}
body_len = get_mka_param_body_len(hdr);
if (body_len < 28) {
wpa_printf(MSG_ERROR,
- "KaY: MKA Use SAK Packet Body Length (%d bytes) should be 28 or more octets",
- (int) body_len);
+ "KaY: MKA Use SAK Packet Body Length (%zu bytes) should be 28 or more octets",
+ body_len);
return -1;
}
body_len = get_mka_param_body_len(hdr);
if (body_len < 5) {
wpa_printf(MSG_ERROR,
- "KaY: MKA Use SAK Packet Body Length (%d bytes) should be 5 or more octets",
- (int) body_len);
+ "KaY: MKA Use SAK Packet Body Length (%zu bytes) should be 5 or more octets",
+ body_len);
return -1;
}
}
-static struct mka_param_body_handler mak_body_handler[] = {
+static struct mka_param_body_handler mka_body_handler[] = {
/* basic parameter set */
{
ieee802_1x_mka_encode_basic_body,
eapol_hdr->type = IEEE802_1X_TYPE_EAPOL_MKA;
eapol_hdr->length = host_to_be16(pbuf->size - pbuf->used);
- for (i = 0; i < ARRAY_SIZE(mak_body_handler); i++) {
- if (mak_body_handler[i].body_present &&
- mak_body_handler[i].body_present(participant)) {
- if (mak_body_handler[i].body_tx(participant, pbuf))
+ for (i = 0; i < ARRAY_SIZE(mka_body_handler); i++) {
+ if (mka_body_handler[i].body_present &&
+ mka_body_handler[i].body_present(participant)) {
+ if (mka_body_handler[i].body_tx(participant, pbuf))
return -1;
}
}
wpa_printf(MSG_DEBUG, "KaY: to enpacket and send the MKPDU");
length += sizeof(struct ieee802_1x_hdr) + sizeof(struct ieee8023_hdr);
- for (i = 0; i < ARRAY_SIZE(mak_body_handler); i++) {
- if (mak_body_handler[i].body_present &&
- mak_body_handler[i].body_present(participant))
- length += mak_body_handler[i].body_length(participant);
+ for (i = 0; i < ARRAY_SIZE(mka_body_handler); i++) {
+ if (mka_body_handler[i].body_present &&
+ mka_body_handler[i].body_present(participant))
+ length += mka_body_handler[i].body_length(participant);
}
buf = wpabuf_alloc(length);
dl_list_add(&psc->sa_list, &psa->list);
wpa_printf(MSG_DEBUG,
- "KaY: Create transmit SA(an: %d, next_PN: %u) of SC(channel: %d)",
- (int) an, next_PN, psc->channel);
+ "KaY: Create transmit SA(an: %hhu, next_PN: %u) of SC(channel: %d)",
+ an, next_PN, psc->channel);
return psa;
}
{
psa->pkey = NULL;
wpa_printf(MSG_DEBUG,
- "KaY: Delete transmit SA(an: %d) of SC(channel: %d)",
- psa->an, psa->sc->channel);
+ "KaY: Delete transmit SA(an: %hhu) of SC",
+ psa->an);
dl_list_del(&psa->list);
os_free(psa);
}
/* EAPOL-MKA body should comprise basic parameter set and ICV */
if (mka_msg_len < MKA_HDR_LEN + body_len + DEFAULT_ICV_LEN) {
wpa_printf(MSG_ERROR,
- "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",
- (int) mka_msg_len, (int) MKA_HDR_LEN,
- (int) body_len, DEFAULT_ICV_LEN);
+ "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",
+ mka_msg_len, MKA_HDR_LEN,
+ body_len, DEFAULT_ICV_LEN);
return -1;
}
if (left_len < (MKA_HDR_LEN + body_len + DEFAULT_ICV_LEN)) {
wpa_printf(MSG_ERROR,
- "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",
- (int) left_len, (int) MKA_HDR_LEN,
- (int) body_len, DEFAULT_ICV_LEN);
+ "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",
+ left_len, MKA_HDR_LEN,
+ body_len, DEFAULT_ICV_LEN);
goto next_para_set;
}
goto next_para_set;
handled[body_type] = TRUE;
- if (body_type < ARRAY_SIZE(mak_body_handler) &&
- mak_body_handler[body_type].body_rx) {
- mak_body_handler[body_type].body_rx
+ if (body_type < ARRAY_SIZE(mka_body_handler) &&
+ mka_body_handler[body_type].body_rx) {
+ mka_body_handler[body_type].body_rx
(participant, pos, left_len);
} else {
wpa_printf(MSG_ERROR,
- "The type %d not supported in this MKA version %d",
+ "The type %d is not supported in this MKA version %d",
body_type, MKA_VERSION_ID);
}