#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))
}
-static int get_mka_param_body_type(const void *body)
+static u8 get_mka_param_body_type(const void *body)
{
const struct ieee802_1x_mka_hdr *hdr = body;
return hdr->type;
wpa_printf(MSG_DEBUG, "\tPriority......: %d", body->priority);
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_capbility);
- wpa_printf(MSG_DEBUG, "\tBody Length...: %d", (int) body_len);
+ wpa_printf(MSG_DEBUG, "\tMACSecCapable.: %d", body->macsec_capability);
+ 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",
size_t body_len;
size_t i;
u8 *mi;
- u32 mn;
+ be32 mn;
if (body == NULL)
return;
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;
+}
+
+
+static Boolean sci_equal(const struct ieee802_1x_mka_sci *a,
+ const struct ieee802_1x_mka_sci *b)
+{
+ return os_memcmp(a, b, sizeof(struct ieee802_1x_mka_sci)) == 0;
}
dl_list_for_each(peer, &participant->live_peers,
struct ieee802_1x_kay_peer, list) {
- if (os_memcmp(&peer->sci, sci, sizeof(peer->sci)) == 0)
+ if (sci_equal(&peer->sci, sci))
return peer;
}
dl_list_for_each(peer, &participant->potential_peers,
struct ieee802_1x_kay_peer, list) {
- if (os_memcmp(&peer->sci, sci, sizeof(peer->sci)) == 0)
+ if (sci_equal(&peer->sci, sci))
return peer;
}
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));
- dl_list_add(&participant->live_peers, &peer->list);
secy_get_available_receive_sc(participant->kay, &sc_ch);
rxsc = ieee802_1x_kay_init_receive_sc(&peer->sci, sc_ch);
- if (!rxsc)
+ if (!rxsc) {
+ os_free(peer);
return NULL;
+ }
+ dl_list_add(&participant->live_peers, &peer->list);
dl_list_add(&participant->rxsc_list, &rxsc->list);
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);
+ if (!rxsc)
+ return NULL;
os_memcpy(&peer->sci, &participant->current_peer_sci,
sizeof(peer->sci));
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);
secy_get_available_receive_sc(participant->kay, &sc_ch);
- rxsc = ieee802_1x_kay_init_receive_sc(&peer->sci, sc_ch);
- if (!rxsc)
- return NULL;
-
dl_list_add(&participant->rxsc_list, &rxsc->list);
secy_create_receive_sc(participant->kay, rxsc);
length = sizeof(struct ieee802_1x_mka_basic_body);
length += participant->ckn.len;
- return (length + 0x3) & ~0x3;
+ return MKA_ALIGN_LENGTH(length);
}
body->key_server = participant->can_be_key_server;
body->macsec_desired = kay->macsec_desired;
- body->macsec_capbility = kay->macsec_capable;
+ body->macsec_capability = kay->macsec_capable;
set_mka_param_body_len(body, length - MKA_HDR_LEN);
os_memcpy(body->actor_sci.addr, kay->actor_sci.addr,
sizeof(kay->actor_sci.addr));
- body->actor_sci.port = host_to_be16(kay->actor_sci.port);
+ body->actor_sci.port = kay->actor_sci.port;
os_memcpy(body->actor_mi, participant->mi, sizeof(body->actor_mi));
participant->mn = participant->mn + 1;
/* If the peer's MI is my MI, I will choose new MI */
if (os_memcmp(body->actor_mi, participant->mi, MI_LEN) == 0) {
- os_get_random(participant->mi, sizeof(participant->mi));
+ if (os_get_random(participant->mi, sizeof(participant->mi)) < 0)
+ return NULL;
participant->mn = 0;
}
os_memcpy(participant->current_peer_id.mi, body->actor_mi, MI_LEN);
- participant->current_peer_id.mn = be_to_host32(body->actor_mn);
+ participant->current_peer_id.mn = body->actor_mn;
os_memcpy(participant->current_peer_sci.addr, body->actor_sci.addr,
sizeof(participant->current_peer_sci.addr));
- participant->current_peer_sci.port = be_to_host16(body->actor_sci.port);
+ participant->current_peer_sci.port = body->actor_sci.port;
/* handler peer */
peer = ieee802_1x_kay_get_peer(participant, body->actor_mi);
return NULL;
peer->macsec_desired = body->macsec_desired;
- peer->macsec_capbility = body->macsec_capbility;
+ peer->macsec_capability = body->macsec_capability;
peer->is_key_server = (Boolean) body->key_server;
peer->key_server_priority = body->priority;
} else if (peer->mn < be_to_host32(body->actor_mn)) {
peer->mn = be_to_host32(body->actor_mn);
peer->expire = time(NULL) + MKA_LIFE_TIME / 1000;
peer->macsec_desired = body->macsec_desired;
- peer->macsec_capbility = body->macsec_capbility;
+ peer->macsec_capability = body->macsec_capability;
peer->is_key_server = (Boolean) body->key_server;
peer->key_server_priority = body->priority;
} else {
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);
}
struct ieee802_1x_mka_hdr *hdr;
size_t body_len;
size_t left_len;
- int body_type;
+ u8 body_type;
u32 peer_mn;
+ be32 _peer_mn;
const u8 *peer_mi;
const u8 *pos;
size_t i;
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;
}
for (i = 0; i < body_len; i += MI_LEN + sizeof(peer_mn)) {
peer_mi = MKA_HDR_LEN + pos + i;
- os_memcpy(&peer_mn, peer_mi + MI_LEN, sizeof(peer_mn));
- peer_mn = be_to_host32(peer_mn);
+ os_memcpy(&_peer_mn, peer_mi + MI_LEN,
+ sizeof(_peer_mn));
+ peer_mn = be_to_host32(_peer_mn);
if (os_memcmp(peer_mi, participant->mi, MI_LEN) == 0 &&
peer_mn == participant->mn) {
included = TRUE;
struct ieee802_1x_kay_peer *peer;
size_t body_len;
u32 peer_mn;
+ be32 _peer_mn;
const u8 *peer_mi;
size_t i;
Boolean is_included;
hdr = (const struct ieee802_1x_mka_hdr *) peer_msg;
body_len = get_mka_param_body_len(hdr);
+ if (body_len % 16 != 0) {
+ wpa_printf(MSG_ERROR,
+ "KaY: MKA Peer Packet Body Length (%zu bytes) should be a multiple of 16 octets",
+ body_len);
+ return -1;
+ }
for (i = 0; i < body_len; i += MI_LEN + sizeof(peer_mn)) {
peer_mi = MKA_HDR_LEN + peer_msg + i;
- os_memcpy(&peer_mn, peer_mi + MI_LEN, sizeof(peer_mn));
- peer_mn = be_to_host32(peer_mn);
+ os_memcpy(&_peer_mn, peer_mi + MI_LEN, sizeof(_peer_mn));
+ peer_mn = be_to_host32(_peer_mn);
/* it is myself */
if (os_memcmp(peer_mi, participant->mi, MI_LEN) == 0) {
/* My message id is used by other participant */
if (peer_mn > participant->mn) {
- os_get_random(participant->mi,
- sizeof(participant->mi));
+ if (os_get_random(participant->mi,
+ sizeof(participant->mi)) < 0)
+ wpa_printf(MSG_DEBUG,
+ "KaY: Could not update mi");
participant->mn = 0;
}
continue;
struct ieee802_1x_mka_hdr *hdr;
size_t body_len;
u32 peer_mn;
+ be32 _peer_mn;
const u8 *peer_mi;
size_t i;
hdr = (struct ieee802_1x_mka_hdr *) peer_msg;
body_len = get_mka_param_body_len(hdr);
+ if (body_len % 16 != 0) {
+ wpa_printf(MSG_ERROR,
+ "KaY: MKA Peer Packet Body Length (%zu bytes) should be a multiple of 16 octets",
+ body_len);
+ return -1;
+ }
for (i = 0; i < body_len; i += MI_LEN + sizeof(peer_mn)) {
peer_mi = MKA_HDR_LEN + peer_msg + i;
- os_memcpy(&peer_mn, peer_mi + MI_LEN, sizeof(peer_mn));
- peer_mn = be_to_host32(peer_mn);
+ os_memcpy(&_peer_mn, peer_mi + MI_LEN, sizeof(_peer_mn));
+ peer_mn = be_to_host32(_peer_mn);
/* it is myself */
if (os_memcmp(peer_mi, participant->mi, MI_LEN) == 0) {
/* My message id is used by other participant */
if (peer_mn > participant->mn) {
- os_get_random(participant->mi,
- sizeof(participant->mi));
+ if (os_get_random(participant->mi,
+ sizeof(participant->mi)) < 0)
+ wpa_printf(MSG_DEBUG,
+ "KaY: Could not update mi");
participant->mn = 0;
}
continue;
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);
}
u32 pn = 1;
length = ieee802_1x_mka_get_sak_use_length(participant);
- body = wpabuf_put(buf, sizeof(struct ieee802_1x_mka_sak_use_body));
+ body = wpabuf_put(buf, length);
body->type = MKA_SAK_USE;
set_mka_param_body_len(body, length - MKA_HDR_LEN);
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;
}
if (body->ltx || body->lrx) {
founded = FALSE;
os_memcpy(ki.mi, body->lsrv_mi, sizeof(ki.mi));
- ki.kn = ntohl(body->lkn);
+ ki.kn = be_to_host32(body->lkn);
dl_list_for_each(sa_key, &participant->sak_list,
struct data_key, list) {
if (is_ki_equal(&sa_key->key_identifier, &ki)) {
}
if (os_memcmp(participant->lki.mi, body->lsrv_mi,
sizeof(participant->lki.mi)) == 0 &&
- ntohl(body->lkn) == participant->lki.kn &&
+ be_to_host32(body->lkn) == participant->lki.kn &&
body->lan == participant->lan) {
peer->sak_used = TRUE;
}
if (body->otx || body->orx) {
if (os_memcmp(participant->oki.mi, body->osrv_mi,
sizeof(participant->oki.mi)) != 0 ||
- ntohl(body->okn) != participant->oki.kn ||
+ be_to_host32(body->okn) != participant->oki.kn ||
body->oan != participant->oan) {
wpa_printf(MSG_WARNING, "KaY: Old key is invalid");
return -1;
}
/* TODO: how to set the MACsec hardware when delay_protect is true */
- if (body->delay_protect && (!ntohl(body->llpn) || !ntohl(body->olpn))) {
+ if (body->delay_protect &&
+ (!be_to_host32(body->llpn) || !be_to_host32(body->olpn))) {
wpa_printf(MSG_WARNING,
"KaY: Lowest packet number should greater than 0 when delay_protect is TRUE");
return -1;
}
/* if i'm key server, and detects peer member pn exhaustion, rekey.*/
- lpn = ntohl(body->llpn);
+ lpn = be_to_host32(body->llpn);
if (lpn > participant->kay->pn_exhaustion) {
if (participant->is_key_server) {
participant->new_sak = TRUE;
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);
}
os_memcpy(body->sak, cipher_suite_tbl[cs_index].id, CS_ID_LEN);
sak_pos = CS_ID_LEN;
}
- if (aes_wrap(participant->kek.key,
+ if (aes_wrap(participant->kek.key, 16,
cipher_suite_tbl[cs_index].sak_len / 8,
sak->key, body->sak + sak_pos)) {
wpa_printf(MSG_ERROR, "KaY: AES wrap failed");
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;
}
"KaY: The key server is not in my live peers list");
return -1;
}
- if (os_memcmp(&participant->kay->key_server_sci,
- &peer->sci, sizeof(struct ieee802_1x_mka_sci)) != 0) {
+ if (!sci_equal(&participant->kay->key_server_sci, &peer->sci)) {
wpa_printf(MSG_ERROR, "KaY: The key server is not elected");
return -1;
}
wpa_printf(MSG_ERROR, "KaY-%s: Out of memory", __func__);
return -1;
}
- if (aes_unwrap(participant->kek.key, sak_len >> 3, wrap_sak,
+ if (aes_unwrap(participant->kek.key, 16, sak_len >> 3, wrap_sak,
unwrap_sak)) {
wpa_printf(MSG_ERROR, "KaY: AES unwrap failed");
os_free(unwrap_sak);
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);
}
struct ieee802_1x_mka_icv_body *body;
size_t body_len;
size_t left_len;
- int body_type;
+ u8 body_type;
const u8 *pos;
pos = mka_msg;
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,
/**
* ieee802_1x_kay_deinit_data_key -
*/
-void ieee802_1x_kay_deinit_data_key(struct data_key *pkey)
+static void ieee802_1x_kay_deinit_data_key(struct data_key *pkey)
{
if (!pkey)
return;
return -1;
}
ctx_offset = 0;
- os_get_random(context + ctx_offset, conf->key_len);
+ if (os_get_random(context + ctx_offset, conf->key_len) < 0) {
+ os_free(context);
+ os_free(conf->key);
+ os_free(conf);
+ return -1;
+ }
ctx_offset += conf->key_len;
dl_list_for_each(peer, &participant->live_peers,
struct ieee802_1x_kay_peer, list) {
struct ieee802_1x_kay_peer *key_server = NULL;
struct ieee802_1x_kay *kay = participant->kay;
Boolean i_is_key_server;
- int i;
if (participant->is_obliged_key_server) {
participant->new_sak = TRUE;
key_server = peer;
} else if (peer->key_server_priority ==
key_server->key_server_priority) {
- for (i = 0; i < 6; i++) {
- if (peer->sci.addr[i] <
- key_server->sci.addr[i])
- key_server = peer;
- }
+ if (os_memcmp(peer->sci.addr, key_server->sci.addr,
+ ETH_ALEN) < 0)
+ key_server = peer;
}
}
i_is_key_server = TRUE;
} else if (kay->actor_priority
== key_server->key_server_priority) {
- for (i = 0; i < 6; i++) {
- if (kay->actor_sci.addr[i]
- < key_server->sci.addr[i]) {
- i_is_key_server = TRUE;
- }
- }
+ if (os_memcmp(kay->actor_sci.addr, key_server->sci.addr,
+ ETH_ALEN) < 0)
+ i_is_key_server = TRUE;
}
- }
-
- if (!key_server && !i_is_key_server) {
- participant->principal = FALSE;
- participant->is_key_server = FALSE;
- participant->is_elected = FALSE;
- return 0;
+ } else if (participant->can_be_key_server) {
+ i_is_key_server = TRUE;
}
if (i_is_key_server) {
ieee802_1x_cp_set_electedself(kay->cp, TRUE);
- if (os_memcmp(&kay->key_server_sci, &kay->actor_sci,
- sizeof(kay->key_server_sci))) {
+ if (!sci_equal(&kay->key_server_sci, &kay->actor_sci)) {
ieee802_1x_cp_signal_chgdserver(kay->cp);
ieee802_1x_cp_sm_step(kay->cp);
}
os_memcpy(&kay->key_server_sci, &kay->actor_sci,
sizeof(kay->key_server_sci));
kay->key_server_priority = kay->actor_priority;
- }
-
- if (key_server) {
+ } else if (key_server) {
ieee802_1x_cp_set_electedself(kay->cp, FALSE);
- if (os_memcmp(&kay->key_server_sci, &key_server->sci,
- sizeof(kay->key_server_sci))) {
+ if (!sci_equal(&kay->key_server_sci, &key_server->sci)) {
ieee802_1x_cp_signal_chgdserver(kay->cp);
ieee802_1x_cp_sm_step(kay->cp);
}
os_memcpy(&kay->key_server_sci, &key_server->sci,
sizeof(kay->key_server_sci));
kay->key_server_priority = key_server->key_server_priority;
+ } else {
+ participant->principal = FALSE;
+ participant->is_key_server = FALSE;
+ participant->is_elected = FALSE;
}
return 0;
if (!peer->macsec_desired)
continue;
- if (peer->macsec_capbility == MACSEC_CAP_NOT_IMPLEMENTED)
+ if (peer->macsec_capability == MACSEC_CAP_NOT_IMPLEMENTED)
continue;
- less_capability = (less_capability < peer->macsec_capbility) ?
- less_capability : peer->macsec_capbility;
+ less_capability = (less_capability < peer->macsec_capability) ?
+ less_capability : peer->macsec_capability;
has_peer = TRUE;
}
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_for_each_safe(rxsc, pre_rxsc,
&participant->rxsc_list,
struct receive_sc, list) {
- if (os_memcmp(&rxsc->sci, &peer->sci,
- sizeof(rxsc->sci)) == 0) {
+ if (sci_equal(&rxsc->sci, &peer->sci)) {
secy_delete_receive_sc(kay, rxsc);
ieee802_1x_kay_deinit_receive_sc(
participant, rxsc);
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;
}
struct ieee802_1x_mka_hdr *hdr;
size_t body_len;
size_t left_len;
- int body_type;
+ u8 body_type;
int i;
const u8 *pos;
Boolean my_included;
if (!ieee802_1x_kay_create_live_peer(
participant,
participant->current_peer_id.mi,
- participant->current_peer_id.mn))
+ be_to_host32(
+ participant->current_peer_id.mn)))
return -1;
ieee802_1x_kay_elect_key_server(participant);
ieee802_1x_kay_decide_macsec_use(participant);
}
if (ieee802_1x_kay_is_in_potential_peer(
participant, participant->current_peer_id.mi)) {
- ieee802_1x_kay_move_live_peer(
- participant, participant->current_peer_id.mi,
- participant->current_peer_id.mn);
+ if (!ieee802_1x_kay_move_live_peer(
+ participant,
+ participant->current_peer_id.mi,
+ be_to_host32(participant->
+ current_peer_id.mn)))
+ return -1;
ieee802_1x_kay_elect_key_server(participant);
ieee802_1x_kay_decide_macsec_use(participant);
}
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 (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);
}
eth_hdr = (struct ieee8023_hdr *) buf;
eapol_hdr = (struct ieee802_1x_hdr *) (eth_hdr + 1);
if (len != sizeof(*eth_hdr) + sizeof(*eapol_hdr) +
- ntohs(eapol_hdr->length)) {
+ be_to_host16(eapol_hdr->length)) {
wpa_printf(MSG_MSGDUMP, "KAY: EAPOL MPDU is invalid: (%lu-%lu)",
(unsigned long) len,
- (unsigned long) ntohs(eapol_hdr->length));
+ (unsigned long) be_to_host16(eapol_hdr->length));
return;
}
eapol_hdr->version);
return;
}
- if (ntohs(eth_hdr->ethertype) != ETH_P_PAE ||
+ if (be_to_host16(eth_hdr->ethertype) != ETH_P_PAE ||
eapol_hdr->type != IEEE802_1X_TYPE_EAPOL_MKA)
return;
os_strlcpy(kay->if_name, ifname, IFNAMSIZ);
os_memcpy(kay->actor_sci.addr, addr, ETH_ALEN);
- kay->actor_sci.port = 0x0001;
+ kay->actor_sci.port = host_to_be16(0x0001);
kay->actor_priority = DEFAULT_PRIO_NOT_KEY_SERVER;
/* While actor acts as a key server, shall distribute sakey */
kay->macsec_capable = MACSEC_CAP_NOT_IMPLEMENTED;
kay->macsec_desired = FALSE;
kay->macsec_protect = FALSE;
- kay->macsec_validate = FALSE;
+ kay->macsec_validate = Disabled;
kay->macsec_replay_protect = FALSE;
kay->macsec_replay_window = 0;
kay->macsec_confidentiality = CONFIDENTIALITY_NONE;
kay->macsec_capable = MACSEC_CAP_INTEG_AND_CONF_0_30_50;
kay->macsec_desired = TRUE;
kay->macsec_protect = TRUE;
- kay->macsec_validate = TRUE;
+ kay->macsec_validate = Strict;
kay->macsec_replay_protect = FALSE;
kay->macsec_replay_window = 0;
kay->macsec_confidentiality = CONFIDENTIALITY_OFFSET_0;
default:
participant->is_obliged_key_server = FALSE;
participant->can_be_key_server = TRUE;
- participant->is_key_server = FALSE;
+ participant->is_key_server = TRUE;
participant->is_elected = FALSE;
break;
}
participant->retry_count = 0;
participant->kay = kay;
- os_get_random(participant->mi, sizeof(participant->mi));
+ if (os_get_random(participant->mi, sizeof(participant->mi)) < 0)
+ goto fail;
participant->mn = 0;
participant->lrx = FALSE;
dl_list_init(&participant->rxsc_list);
participant->txsc = ieee802_1x_kay_init_transmit_sc(&kay->actor_sci,
kay->sc_ch);
+ secy_cp_control_protect_frames(kay, kay->macsec_protect);
+ secy_cp_control_replay(kay, kay->macsec_replay_protect,
+ kay->macsec_replay_window);
secy_create_transmit_sc(kay, participant->txsc);
/* to derive KEK from CAK and CKN */
return;
}
+ eloop_cancel_timeout(ieee802_1x_participant_timer, participant, NULL);
dl_list_del(&participant->list);
/* remove live peer */