From 6d014ffc6e654e7e802263c55ce568df153a1e1c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 2 Sep 2015 22:55:03 +0300 Subject: [PATCH] Make struct wpa_eapol_key easier to use with variable length MIC Suite B 192-bit addition from IEEE Std 802.11ac-2013 replaced the previous fixed length Key MIC field with a variable length field. That change was addressed with an addition of a new struct defined for the second MIC length. This is not really scalable and with FILS coming up with a zero-length MIC case for AEAD, a more thorough change to support variable length MIC is needed. Remove the Key MIC and Key Data Length fields from the struct wpa_eapol_key and find their location based on the MIC length information (which is determined by the AKMP). This change allows the separate struct wpa_eapol_key_192 to be removed since struct wpa_eapol_key will now include only the fixed length fields that are shared with all EAPOL-Key cases in IEEE Std 802.11. Signed-off-by: Jouni Malinen --- src/ap/wpa_auth.c | 59 +++++++--------------- src/common/wpa_common.h | 21 ++------ src/rsn_supp/peerkey.c | 93 +++++++++++++++++----------------- src/rsn_supp/peerkey.h | 2 +- src/rsn_supp/wpa.c | 99 ++++++++++++++----------------------- wlantest/rx_data.c | 2 +- wlantest/rx_eapol.c | 107 +++++++++++++++++++++++++++------------- wlantest/wlantest.h | 3 +- 8 files changed, 181 insertions(+), 205 deletions(-) diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 358708648..8bc4abe95 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -877,7 +877,6 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, { struct ieee802_1x_hdr *hdr; struct wpa_eapol_key *key; - struct wpa_eapol_key_192 *key192; u16 key_info, key_data_length; enum { PAIRWISE_2, PAIRWISE_4, GROUP_2, REQUEST, SMK_M1, SMK_M3, SMK_ERROR } msg; @@ -886,27 +885,23 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, int ft; const u8 *eapol_key_ie, *key_data; size_t eapol_key_ie_len, keyhdrlen, mic_len; + u8 *mic; if (wpa_auth == NULL || !wpa_auth->conf.wpa || sm == NULL) return; mic_len = wpa_mic_len(sm->wpa_key_mgmt); - keyhdrlen = mic_len == 24 ? sizeof(*key192) : sizeof(*key); + keyhdrlen = sizeof(*key) + mic_len + 2; if (data_len < sizeof(*hdr) + keyhdrlen) return; hdr = (struct ieee802_1x_hdr *) data; key = (struct wpa_eapol_key *) (hdr + 1); - key192 = (struct wpa_eapol_key_192 *) (hdr + 1); + mic = (u8 *) (key + 1); key_info = WPA_GET_BE16(key->key_info); - if (mic_len == 24) { - key_data = (const u8 *) (key192 + 1); - key_data_length = WPA_GET_BE16(key192->key_data_length); - } else { - key_data = (const u8 *) (key + 1); - key_data_length = WPA_GET_BE16(key->key_data_length); - } + key_data = mic + mic_len + 2; + key_data_length = WPA_GET_BE16(mic + mic_len); wpa_printf(MSG_DEBUG, "WPA: Received EAPOL-Key from " MACSTR " key_info=0x%x type=%u key_data_length=%u", MAC2STR(sm->addr), key_info, key->type, key_data_length); @@ -1412,17 +1407,16 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, { struct ieee802_1x_hdr *hdr; struct wpa_eapol_key *key; - struct wpa_eapol_key_192 *key192; size_t len, mic_len, keyhdrlen; int alg; int key_data_len, pad_len = 0; u8 *buf, *pos; int version, pairwise; int i; - u8 *key_data; + u8 *key_mic, *key_data; mic_len = wpa_mic_len(sm->wpa_key_mgmt); - keyhdrlen = mic_len == 24 ? sizeof(*key192) : sizeof(*key); + keyhdrlen = sizeof(*key) + mic_len + 2; len = sizeof(struct ieee802_1x_hdr) + keyhdrlen; @@ -1471,7 +1465,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, hdr->type = IEEE802_1X_TYPE_EAPOL_KEY; hdr->length = host_to_be16(len - sizeof(*hdr)); key = (struct wpa_eapol_key *) (hdr + 1); - key192 = (struct wpa_eapol_key_192 *) (hdr + 1); + key_mic = (u8 *) (key + 1); key_data = ((u8 *) (hdr + 1)) + keyhdrlen; key->type = sm->wpa == WPA_VERSION_WPA2 ? @@ -1510,10 +1504,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, if (kde && !encr) { os_memcpy(key_data, kde, kde_len); - if (mic_len == 24) - WPA_PUT_BE16(key192->key_data_length, kde_len); - else - WPA_PUT_BE16(key->key_data_length, kde_len); + WPA_PUT_BE16(key_mic + mic_len, kde_len); } else if (encr && kde) { buf = os_zalloc(key_data_len); if (buf == NULL) { @@ -1539,12 +1530,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, os_free(buf); return; } - if (mic_len == 24) - WPA_PUT_BE16(key192->key_data_length, - key_data_len); - else - WPA_PUT_BE16(key->key_data_length, - key_data_len); + WPA_PUT_BE16(key_mic + mic_len, key_data_len); #ifndef CONFIG_NO_RC4 } else if (sm->PTK.kek_len == 16) { u8 ek[32]; @@ -1555,12 +1541,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, os_memcpy(ek + 16, sm->PTK.kek, sm->PTK.kek_len); os_memcpy(key_data, buf, key_data_len); rc4_skip(ek, 32, 256, key_data, key_data_len); - if (mic_len == 24) - WPA_PUT_BE16(key192->key_data_length, - key_data_len); - else - WPA_PUT_BE16(key->key_data_length, - key_data_len); + WPA_PUT_BE16(key_mic + mic_len, key_data_len); #endif /* CONFIG_NO_RC4 */ } else { os_free(hdr); @@ -1571,8 +1552,6 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, } if (key_info & WPA_KEY_INFO_MIC) { - u8 *key_mic; - if (!sm->PTK_valid) { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "PTK not valid when sending EAPOL-Key " @@ -1581,7 +1560,6 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, return; } - key_mic = key192->key_mic; /* same offset for key and key192 */ wpa_eapol_key_mic(sm->PTK.kck, sm->PTK.kck_len, sm->wpa_key_mgmt, version, (u8 *) hdr, len, key_mic); @@ -1641,10 +1619,9 @@ static int wpa_verify_key_mic(int akmp, struct wpa_ptk *PTK, u8 *data, { struct ieee802_1x_hdr *hdr; struct wpa_eapol_key *key; - struct wpa_eapol_key_192 *key192; u16 key_info; int ret = 0; - u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN]; + u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN], *mic_pos; size_t mic_len = wpa_mic_len(akmp); if (data_len < sizeof(*hdr) + sizeof(*key)) @@ -1652,16 +1629,16 @@ static int wpa_verify_key_mic(int akmp, struct wpa_ptk *PTK, u8 *data, hdr = (struct ieee802_1x_hdr *) data; key = (struct wpa_eapol_key *) (hdr + 1); - key192 = (struct wpa_eapol_key_192 *) (hdr + 1); + mic_pos = (u8 *) (key + 1); key_info = WPA_GET_BE16(key->key_info); - os_memcpy(mic, key192->key_mic, mic_len); - os_memset(key192->key_mic, 0, mic_len); + os_memcpy(mic, mic_pos, mic_len); + os_memset(mic_pos, 0, mic_len); if (wpa_eapol_key_mic(PTK->kck, PTK->kck_len, akmp, key_info & WPA_KEY_INFO_TYPE_MASK, - data, data_len, key192->key_mic) || - os_memcmp_const(mic, key192->key_mic, mic_len) != 0) + data, data_len, mic_pos) || + os_memcmp_const(mic, mic_pos, mic_len) != 0) ret = -1; - os_memcpy(key192->key_mic, mic, mic_len); + os_memcpy(mic_pos, mic, mic_len); return ret; } diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h index ea8f7590a..cff404fde 100644 --- a/src/common/wpa_common.h +++ b/src/common/wpa_common.h @@ -183,24 +183,9 @@ struct wpa_eapol_key { u8 key_iv[16]; u8 key_rsc[WPA_KEY_RSC_LEN]; u8 key_id[8]; /* Reserved in IEEE 802.11i/RSN */ - u8 key_mic[16]; - u8 key_data_length[2]; /* big endian */ - /* followed by key_data_length bytes of key_data */ -} STRUCT_PACKED; - -struct wpa_eapol_key_192 { - u8 type; - /* Note: key_info, key_length, and key_data_length are unaligned */ - u8 key_info[2]; /* big endian */ - u8 key_length[2]; /* big endian */ - u8 replay_counter[WPA_REPLAY_COUNTER_LEN]; - u8 key_nonce[WPA_NONCE_LEN]; - u8 key_iv[16]; - u8 key_rsc[WPA_KEY_RSC_LEN]; - u8 key_id[8]; /* Reserved in IEEE 802.11i/RSN */ - u8 key_mic[24]; - u8 key_data_length[2]; /* big endian */ - /* followed by key_data_length bytes of key_data */ + /* variable length Key MIC field */ + /* big endian 2-octet Key Data Length field */ + /* followed by Key Data Length bytes of Key Data */ } STRUCT_PACKED; #define WPA_EAPOL_KEY_MIC_MAX_LEN 24 diff --git a/src/rsn_supp/peerkey.c b/src/rsn_supp/peerkey.c index 79764d94b..33324b1bb 100644 --- a/src/rsn_supp/peerkey.c +++ b/src/rsn_supp/peerkey.c @@ -65,10 +65,9 @@ static int wpa_supplicant_send_smk_error(struct wpa_sm *sm, const u8 *dst, { size_t rlen; struct wpa_eapol_key *err; - struct wpa_eapol_key_192 *err192; struct rsn_error_kde error; - u8 *rbuf, *pos; - size_t kde_len; + u8 *rbuf, *pos, *mic; + size_t kde_len, mic_len = 16; u16 key_info; kde_len = 2 + RSN_SELECTOR_LEN + sizeof(error); @@ -76,11 +75,11 @@ static int wpa_supplicant_send_smk_error(struct wpa_sm *sm, const u8 *dst, kde_len += 2 + RSN_SELECTOR_LEN + ETH_ALEN; rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, - NULL, sizeof(*err) + kde_len, &rlen, - (void *) &err); + NULL, sizeof(*err) + mic_len + 2 + kde_len, + &rlen, (void *) &err); if (rbuf == NULL) return -1; - err192 = (struct wpa_eapol_key_192 *) err; + mic = (u8 *) (err + 1); err->type = EAPOL_KEY_TYPE_RSN; key_info = ver | WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC | @@ -92,8 +91,8 @@ static int wpa_supplicant_send_smk_error(struct wpa_sm *sm, const u8 *dst, WPA_REPLAY_COUNTER_LEN); inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN); - WPA_PUT_BE16(err->key_data_length, (u16) kde_len); - pos = (u8 *) (err + 1); + WPA_PUT_BE16(mic + mic_len, (u16) kde_len); + pos = mic + mic_len + 2; if (peer) { /* Peer MAC Address KDE */ @@ -115,7 +114,7 @@ static int wpa_supplicant_send_smk_error(struct wpa_sm *sm, const u8 *dst, } wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver, dst, - ETH_P_EAPOL, rbuf, rlen, err192->key_mic); + ETH_P_EAPOL, rbuf, rlen, mic); return 0; } @@ -128,9 +127,8 @@ static int wpa_supplicant_send_smk_m3(struct wpa_sm *sm, { size_t rlen; struct wpa_eapol_key *reply; - struct wpa_eapol_key_192 *reply192; - u8 *rbuf, *pos; - size_t kde_len; + u8 *rbuf, *pos, *mic; + size_t kde_len, mic_len = 16; u16 key_info; /* KDEs: Peer RSN IE, Initiator MAC Address, Initiator Nonce */ @@ -139,11 +137,10 @@ static int wpa_supplicant_send_smk_m3(struct wpa_sm *sm, 2 + RSN_SELECTOR_LEN + WPA_NONCE_LEN; rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, - NULL, sizeof(*reply) + kde_len, &rlen, - (void *) &reply); + NULL, sizeof(*reply) + mic_len + 2 + kde_len, + &rlen, (void *) &reply); if (rbuf == NULL) return -1; - reply192 = (struct wpa_eapol_key_192 *) reply; reply->type = EAPOL_KEY_TYPE_RSN; key_info = ver | WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC | @@ -155,8 +152,9 @@ static int wpa_supplicant_send_smk_m3(struct wpa_sm *sm, os_memcpy(reply->key_nonce, peerkey->pnonce, WPA_NONCE_LEN); - WPA_PUT_BE16(reply->key_data_length, (u16) kde_len); - pos = (u8 *) (reply + 1); + mic = (u8 *) (reply + 1); + WPA_PUT_BE16(mic + mic_len, (u16) kde_len); + pos = mic + mic_len + 2; /* Peer RSN IE */ pos = wpa_add_ie(pos, peerkey->rsnie_p, peerkey->rsnie_p_len); @@ -169,7 +167,7 @@ static int wpa_supplicant_send_smk_m3(struct wpa_sm *sm, wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK M3"); wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver, src_addr, - ETH_P_EAPOL, rbuf, rlen, reply192->key_mic); + ETH_P_EAPOL, rbuf, rlen, mic); return 0; } @@ -324,18 +322,19 @@ static void wpa_supplicant_send_stk_1_of_4(struct wpa_sm *sm, { size_t mlen; struct wpa_eapol_key *msg; - u8 *mbuf; - size_t kde_len; + u8 *mbuf, *mic; + size_t kde_len, mic_len = 16; u16 key_info, ver; kde_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN; mbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, - sizeof(*msg) + kde_len, &mlen, + sizeof(*msg) + mic_len + 2 + kde_len, &mlen, (void *) &msg); if (mbuf == NULL) return; + mic = (u8 *) (msg + 1); msg->type = EAPOL_KEY_TYPE_RSN; if (peerkey->cipher != WPA_CIPHER_TKIP) @@ -355,8 +354,8 @@ static void wpa_supplicant_send_stk_1_of_4(struct wpa_sm *sm, WPA_REPLAY_COUNTER_LEN); inc_byte_array(peerkey->replay_counter, WPA_REPLAY_COUNTER_LEN); - WPA_PUT_BE16(msg->key_data_length, kde_len); - wpa_add_kde((u8 *) (msg + 1), RSN_KEY_DATA_PMKID, + WPA_PUT_BE16(mic + mic_len, kde_len); + wpa_add_kde(mic + mic_len + 2, RSN_KEY_DATA_PMKID, peerkey->smkid, PMKID_LEN); if (random_get_bytes(peerkey->inonce, WPA_NONCE_LEN)) { @@ -381,8 +380,8 @@ static void wpa_supplicant_send_stk_3_of_4(struct wpa_sm *sm, { size_t mlen; struct wpa_eapol_key *msg; - u8 *mbuf, *pos; - size_t kde_len; + u8 *mbuf, *pos, *mic; + size_t kde_len, mic_len = 16; u16 key_info, ver; be32 lifetime; @@ -390,11 +389,12 @@ static void wpa_supplicant_send_stk_3_of_4(struct wpa_sm *sm, 2 + RSN_SELECTOR_LEN + sizeof(lifetime); mbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, - sizeof(*msg) + kde_len, &mlen, + sizeof(*msg) + mic_len + 2 + kde_len, &mlen, (void *) &msg); if (mbuf == NULL) return; + mic = (u8 *) (msg + 1); msg->type = EAPOL_KEY_TYPE_RSN; if (peerkey->cipher != WPA_CIPHER_TKIP) @@ -415,8 +415,8 @@ static void wpa_supplicant_send_stk_3_of_4(struct wpa_sm *sm, WPA_REPLAY_COUNTER_LEN); inc_byte_array(peerkey->replay_counter, WPA_REPLAY_COUNTER_LEN); - WPA_PUT_BE16(msg->key_data_length, kde_len); - pos = (u8 *) (msg + 1); + WPA_PUT_BE16(mic + mic_len, kde_len); + pos = mic + mic_len; pos = wpa_add_ie(pos, peerkey->rsnie_i, peerkey->rsnie_i_len); lifetime = host_to_be32(peerkey->lifetime); wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME, @@ -427,8 +427,7 @@ static void wpa_supplicant_send_stk_3_of_4(struct wpa_sm *sm, wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key STK 3/4 to " MACSTR, MAC2STR(peerkey->addr)); wpa_eapol_key_send(sm, peerkey->stk.kck, peerkey->stk.kck_len, ver, - peerkey->addr, ETH_P_EAPOL, mbuf, mlen, - msg->key_mic); + peerkey->addr, ETH_P_EAPOL, mbuf, mlen, mic); } @@ -911,10 +910,10 @@ static void wpa_supplicant_process_stk_4_of_4(struct wpa_sm *sm, */ int peerkey_verify_eapol_key_mic(struct wpa_sm *sm, struct wpa_peerkey *peerkey, - struct wpa_eapol_key_192 *key, u16 ver, + struct wpa_eapol_key *key, u16 ver, const u8 *buf, size_t len) { - u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN]; + u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN], *mic_pos; size_t mic_len = 16; int ok = 0; @@ -926,12 +925,13 @@ int peerkey_verify_eapol_key_mic(struct wpa_sm *sm, peerkey->stk_set = 1; } - os_memcpy(mic, key->key_mic, mic_len); + mic_pos = (u8 *) (key + 1); + os_memcpy(mic, mic_pos, mic_len); if (peerkey->tstk_set) { - os_memset(key->key_mic, 0, mic_len); + os_memset(mic_pos, 0, mic_len); wpa_eapol_key_mic(peerkey->tstk.kck, peerkey->tstk.kck_len, - sm->key_mgmt, ver, buf, len, key->key_mic); - if (os_memcmp_const(mic, key->key_mic, mic_len) != 0) { + sm->key_mgmt, ver, buf, len, mic_pos); + if (os_memcmp_const(mic, mic_pos, mic_len) != 0) { wpa_printf(MSG_WARNING, "RSN: Invalid EAPOL-Key MIC " "when using TSTK - ignoring TSTK"); } else { @@ -945,10 +945,10 @@ int peerkey_verify_eapol_key_mic(struct wpa_sm *sm, } if (!ok && peerkey->stk_set) { - os_memset(key->key_mic, 0, mic_len); + os_memset(mic_pos, 0, mic_len); wpa_eapol_key_mic(peerkey->stk.kck, peerkey->stk.kck_len, - sm->key_mgmt, ver, buf, len, key->key_mic); - if (os_memcmp_const(mic, key->key_mic, mic_len) != 0) { + sm->key_mgmt, ver, buf, len, mic_pos); + if (os_memcmp_const(mic, mic_pos, mic_len) != 0) { wpa_printf(MSG_WARNING, "RSN: Invalid EAPOL-Key MIC " "- dropping packet"); return -1; @@ -980,10 +980,10 @@ int peerkey_verify_eapol_key_mic(struct wpa_sm *sm, */ int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer) { - size_t rlen, kde_len; + size_t rlen, kde_len, mic_len; struct wpa_eapol_key *req; int key_info, ver; - u8 bssid[ETH_ALEN], *rbuf, *pos, *count_pos; + u8 bssid[ETH_ALEN], *rbuf, *pos, *count_pos, *mic; u16 count; struct rsn_ie_hdr *hdr; struct wpa_peerkey *peerkey; @@ -999,6 +999,7 @@ int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer) return -1; } + mic_len = wpa_mic_len(sm->key_mgmt); if (sm->pairwise_cipher != WPA_CIPHER_TKIP) ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; else @@ -1047,7 +1048,7 @@ int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer) kde_len = peerkey->rsnie_i_len + 2 + RSN_SELECTOR_LEN + ETH_ALEN; rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, - sizeof(*req) + kde_len, &rlen, + sizeof(*req) + mic_len + 2 + kde_len, &rlen, (void *) &req); if (rbuf == NULL) { wpa_supplicant_peerkey_free(sm, peerkey); @@ -1074,8 +1075,10 @@ int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer) wpa_hexdump(MSG_DEBUG, "WPA: INonce for SMK handshake", req->key_nonce, WPA_NONCE_LEN); - WPA_PUT_BE16(req->key_data_length, (u16) kde_len); - pos = (u8 *) (req + 1); + mic = pos = (u8 *) (req + 1); + pos += mic_len; + WPA_PUT_BE16(pos, (u16) kde_len); + pos += 2; /* Initiator RSN IE */ pos = wpa_add_ie(pos, peerkey->rsnie_i, peerkey->rsnie_i_len); @@ -1085,7 +1088,7 @@ int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer) wpa_printf(MSG_INFO, "RSN: Sending EAPOL-Key SMK M1 Request (peer " MACSTR ")", MAC2STR(peer)); wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver, bssid, - ETH_P_EAPOL, rbuf, rlen, req->key_mic); + ETH_P_EAPOL, rbuf, rlen, mic); peerkey->next = sm->peerkey; sm->peerkey = peerkey; diff --git a/src/rsn_supp/peerkey.h b/src/rsn_supp/peerkey.h index 6ccd948ba..f3d07f3d3 100644 --- a/src/rsn_supp/peerkey.h +++ b/src/rsn_supp/peerkey.h @@ -38,7 +38,7 @@ struct wpa_peerkey { int peerkey_verify_eapol_key_mic(struct wpa_sm *sm, struct wpa_peerkey *peerkey, - struct wpa_eapol_key_192 *key, u16 ver, + struct wpa_eapol_key *key, u16 ver, const u8 *buf, size_t len); void peerkey_rx_eapol_4way(struct wpa_sm *sm, struct wpa_peerkey *peerkey, struct wpa_eapol_key *key, u16 key_info, u16 ver, diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 3c4787925..2c964fd1a 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -97,9 +97,8 @@ void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise) { size_t mic_len, hdrlen, rlen; struct wpa_eapol_key *reply; - struct wpa_eapol_key_192 *reply192; int key_info, ver; - u8 bssid[ETH_ALEN], *rbuf, *key_mic; + u8 bssid[ETH_ALEN], *rbuf, *key_mic, *mic; if (sm->key_mgmt == WPA_KEY_MGMT_OSEN || wpa_key_mgmt_suite_b(sm->key_mgmt)) @@ -119,12 +118,11 @@ void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise) } mic_len = wpa_mic_len(sm->key_mgmt); - hdrlen = mic_len == 24 ? sizeof(*reply192) : sizeof(*reply); + hdrlen = sizeof(*reply) + mic_len + 2; rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, hdrlen, &rlen, (void *) &reply); if (rbuf == NULL) return; - reply192 = (struct wpa_eapol_key_192 *) reply; reply->type = (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) ? @@ -142,14 +140,12 @@ void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise) WPA_REPLAY_COUNTER_LEN); inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN); - if (mic_len == 24) - WPA_PUT_BE16(reply192->key_data_length, 0); - else - WPA_PUT_BE16(reply->key_data_length, 0); + mic = (u8 *) (reply + 1); + WPA_PUT_BE16(mic + mic_len, 0); if (!(key_info & WPA_KEY_INFO_MIC)) key_mic = NULL; else - key_mic = reply192->key_mic; /* same offset in reply */ + key_mic = mic; wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Sending EAPOL-Key Request (error=%d " @@ -341,7 +337,6 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst, { size_t mic_len, hdrlen, rlen; struct wpa_eapol_key *reply; - struct wpa_eapol_key_192 *reply192; u8 *rbuf, *key_mic; u8 *rsn_ie_buf = NULL; @@ -384,7 +379,7 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst, wpa_hexdump(MSG_DEBUG, "WPA: WPA IE for msg 2/4", wpa_ie, wpa_ie_len); mic_len = wpa_mic_len(sm->key_mgmt); - hdrlen = mic_len == 24 ? sizeof(*reply192) : sizeof(*reply); + hdrlen = sizeof(*reply) + mic_len + 2; rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, hdrlen + wpa_ie_len, &rlen, (void *) &reply); @@ -392,7 +387,6 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst, os_free(rsn_ie_buf); return -1; } - reply192 = (struct wpa_eapol_key_192 *) reply; reply->type = (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) ? @@ -408,14 +402,9 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst, wpa_hexdump(MSG_DEBUG, "WPA: Replay Counter", reply->replay_counter, WPA_REPLAY_COUNTER_LEN); - key_mic = reply192->key_mic; /* same offset for reply and reply192 */ - if (mic_len == 24) { - WPA_PUT_BE16(reply192->key_data_length, wpa_ie_len); - os_memcpy(reply192 + 1, wpa_ie, wpa_ie_len); - } else { - WPA_PUT_BE16(reply->key_data_length, wpa_ie_len); - os_memcpy(reply + 1, wpa_ie, wpa_ie_len); - } + key_mic = (u8 *) (reply + 1); + WPA_PUT_BE16(key_mic + mic_len, wpa_ie_len); /* Key Data Length */ + os_memcpy(key_mic + mic_len + 2, wpa_ie, wpa_ie_len); /* Key Data */ os_free(rsn_ie_buf); os_memcpy(reply->key_nonce, nonce, WPA_NONCE_LEN); @@ -1147,16 +1136,14 @@ int wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst, { size_t mic_len, hdrlen, rlen; struct wpa_eapol_key *reply; - struct wpa_eapol_key_192 *reply192; u8 *rbuf, *key_mic; mic_len = wpa_mic_len(sm->key_mgmt); - hdrlen = mic_len == 24 ? sizeof(*reply192) : sizeof(*reply); + hdrlen = sizeof(*reply) + mic_len + 2; rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, hdrlen, &rlen, (void *) &reply); if (rbuf == NULL) return -1; - reply192 = (struct wpa_eapol_key_192 *) reply; reply->type = (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) ? @@ -1171,11 +1158,8 @@ int wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst, os_memcpy(reply->replay_counter, key->replay_counter, WPA_REPLAY_COUNTER_LEN); - key_mic = reply192->key_mic; /* same offset for reply and reply192 */ - if (mic_len == 24) - WPA_PUT_BE16(reply192->key_data_length, 0); - else - WPA_PUT_BE16(reply->key_data_length, 0); + key_mic = (u8 *) (reply + 1); + WPA_PUT_BE16(key_mic + mic_len, 0); wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 4/4"); return wpa_eapol_key_send(sm, ptk->kck, ptk->kck_len, ver, dst, @@ -1456,16 +1440,14 @@ static int wpa_supplicant_send_2_of_2(struct wpa_sm *sm, { size_t mic_len, hdrlen, rlen; struct wpa_eapol_key *reply; - struct wpa_eapol_key_192 *reply192; u8 *rbuf, *key_mic; mic_len = wpa_mic_len(sm->key_mgmt); - hdrlen = mic_len == 24 ? sizeof(*reply192) : sizeof(*reply); + hdrlen = sizeof(*reply) + mic_len + 2; rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, hdrlen, &rlen, (void *) &reply); if (rbuf == NULL) return -1; - reply192 = (struct wpa_eapol_key_192 *) reply; reply->type = (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) ? @@ -1480,11 +1462,8 @@ static int wpa_supplicant_send_2_of_2(struct wpa_sm *sm, os_memcpy(reply->replay_counter, key->replay_counter, WPA_REPLAY_COUNTER_LEN); - key_mic = reply192->key_mic; /* same offset for reply and reply192 */ - if (mic_len == 24) - WPA_PUT_BE16(reply192->key_data_length, 0); - else - WPA_PUT_BE16(reply->key_data_length, 0); + key_mic = (u8 *) (reply + 1); + WPA_PUT_BE16(key_mic + mic_len, 0); wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 2/2"); return wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver, @@ -1564,7 +1543,7 @@ failed: static int wpa_supplicant_verify_eapol_key_mic(struct wpa_sm *sm, - struct wpa_eapol_key_192 *key, + struct wpa_eapol_key *key, u16 ver, const u8 *buf, size_t len) { @@ -1572,12 +1551,12 @@ static int wpa_supplicant_verify_eapol_key_mic(struct wpa_sm *sm, int ok = 0; size_t mic_len = wpa_mic_len(sm->key_mgmt); - os_memcpy(mic, key->key_mic, mic_len); + os_memcpy(mic, key + 1, mic_len); if (sm->tptk_set) { - os_memset(key->key_mic, 0, mic_len); + os_memset(key + 1, 0, mic_len); wpa_eapol_key_mic(sm->tptk.kck, sm->tptk.kck_len, sm->key_mgmt, - ver, buf, len, key->key_mic); - if (os_memcmp_const(mic, key->key_mic, mic_len) != 0) { + ver, buf, len, (u8 *) (key + 1)); + if (os_memcmp_const(mic, key + 1, mic_len) != 0) { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: Invalid EAPOL-Key MIC " "when using TPTK - ignoring TPTK"); @@ -1591,10 +1570,10 @@ static int wpa_supplicant_verify_eapol_key_mic(struct wpa_sm *sm, } if (!ok && sm->ptk_set) { - os_memset(key->key_mic, 0, mic_len); + os_memset(key + 1, 0, mic_len); wpa_eapol_key_mic(sm->ptk.kck, sm->ptk.kck_len, sm->key_mgmt, - ver, buf, len, key->key_mic); - if (os_memcmp_const(mic, key->key_mic, mic_len) != 0) { + ver, buf, len, (u8 *) (key + 1)); + if (os_memcmp_const(mic, key + 1, mic_len) != 0) { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: Invalid EAPOL-Key MIC - " "dropping packet"); @@ -1619,7 +1598,8 @@ static int wpa_supplicant_verify_eapol_key_mic(struct wpa_sm *sm, /* Decrypt RSN EAPOL-Key key data (RC4 or AES-WRAP) */ static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm, - struct wpa_eapol_key *key, u16 ver, + struct wpa_eapol_key *key, + size_t mic_len, u16 ver, u8 *key_data, size_t *key_data_len) { wpa_hexdump(MSG_DEBUG, "RSN: encrypted key data", @@ -1678,7 +1658,7 @@ static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm, } os_memcpy(key_data, buf, *key_data_len); bin_clear_free(buf, *key_data_len); - WPA_PUT_BE16(key->key_data_length, *key_data_len); + WPA_PUT_BE16(((u8 *) (key + 1)) + mic_len, *key_data_len); } else { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: Unsupported key_info type %d", ver); @@ -1763,12 +1743,11 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, size_t plen, data_len, key_data_len; const struct ieee802_1x_hdr *hdr; struct wpa_eapol_key *key; - struct wpa_eapol_key_192 *key192; u16 key_info, ver; u8 *tmp = NULL; int ret = -1; struct wpa_peerkey *peerkey = NULL; - u8 *key_data; + u8 *mic, *key_data; size_t mic_len, keyhdrlen; #ifdef CONFIG_IEEE80211R @@ -1776,7 +1755,7 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, #endif /* CONFIG_IEEE80211R */ mic_len = wpa_mic_len(sm->key_mgmt); - keyhdrlen = mic_len == 24 ? sizeof(*key192) : sizeof(*key); + keyhdrlen = sizeof(*key) + mic_len + 2; if (len < sizeof(*hdr) + keyhdrlen) { wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, @@ -1828,12 +1807,8 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, goto out; os_memcpy(tmp, buf, data_len); key = (struct wpa_eapol_key *) (tmp + sizeof(struct ieee802_1x_hdr)); - key192 = (struct wpa_eapol_key_192 *) - (tmp + sizeof(struct ieee802_1x_hdr)); - if (mic_len == 24) - key_data = (u8 *) (key192 + 1); - else - key_data = (u8 *) (key + 1); + mic = (u8 *) (key + 1); + key_data = mic + mic_len + 2; if (key->type != EAPOL_KEY_TYPE_WPA && key->type != EAPOL_KEY_TYPE_RSN) { @@ -1844,11 +1819,8 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, goto out; } - if (mic_len == 24) - key_data_len = WPA_GET_BE16(key192->key_data_length); - else - key_data_len = WPA_GET_BE16(key->key_data_length); - wpa_eapol_key_dump(sm, key, key_data_len, key192->key_mic, mic_len); + key_data_len = WPA_GET_BE16(mic + mic_len); + wpa_eapol_key_dump(sm, key, key_data_len, mic, mic_len); if (key_data_len > plen - keyhdrlen) { wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Invalid EAPOL-Key " @@ -2004,19 +1976,20 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, } if ((key_info & WPA_KEY_INFO_MIC) && !peerkey && - wpa_supplicant_verify_eapol_key_mic(sm, key192, ver, tmp, data_len)) + wpa_supplicant_verify_eapol_key_mic(sm, key, ver, tmp, data_len)) goto out; #ifdef CONFIG_PEERKEY if ((key_info & WPA_KEY_INFO_MIC) && peerkey && - peerkey_verify_eapol_key_mic(sm, peerkey, key192, ver, tmp, + peerkey_verify_eapol_key_mic(sm, peerkey, key, ver, tmp, data_len)) goto out; #endif /* CONFIG_PEERKEY */ if ((sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) && (key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { - if (wpa_supplicant_decrypt_key_data(sm, key, ver, key_data, + if (wpa_supplicant_decrypt_key_data(sm, key, mic_len, + ver, key_data, &key_data_len)) goto out; } diff --git a/wlantest/rx_data.c b/wlantest/rx_data.c index b53542fac..be004110b 100644 --- a/wlantest/rx_data.c +++ b/wlantest/rx_data.c @@ -59,7 +59,7 @@ static void rx_data_eth(struct wlantest *wt, const u8 *bssid, { switch (ethertype) { case ETH_P_PAE: - rx_data_eapol(wt, dst, src, data, len, prot); + rx_data_eapol(wt, bssid, sta_addr, dst, src, data, len, prot); break; case ETH_P_IP: rx_data_ip(wt, bssid, sta_addr, dst, src, data, len, diff --git a/wlantest/rx_eapol.c b/wlantest/rx_eapol.c index 75bfa7d3e..89effc623 100644 --- a/wlantest/rx_eapol.c +++ b/wlantest/rx_eapol.c @@ -39,7 +39,7 @@ static int check_mic(const u8 *kck, size_t kck_len, int akmp, int ver, struct ieee802_1x_hdr *hdr; struct wpa_eapol_key *key; u8 rx_mic[WPA_EAPOL_KEY_MIC_MAX_LEN]; - size_t mic_len = 16; + size_t mic_len = wpa_mic_len(akmp); buf = os_malloc(len); if (buf == NULL) @@ -48,12 +48,12 @@ static int check_mic(const u8 *kck, size_t kck_len, int akmp, int ver, hdr = (struct ieee802_1x_hdr *) buf; key = (struct wpa_eapol_key *) (hdr + 1); - os_memcpy(rx_mic, key->key_mic, mic_len); - os_memset(key->key_mic, 0, mic_len); + os_memcpy(rx_mic, key + 1, mic_len); + os_memset(key + 1, 0, mic_len); if (wpa_eapol_key_mic(kck, kck_len, akmp, ver, buf, len, - key->key_mic) == 0 && - os_memcmp(rx_mic, key->key_mic, mic_len) == 0) + (u8 *) (key + 1)) == 0 && + os_memcmp(rx_mic, key + 1, mic_len) == 0) ret = 0; os_free(buf); @@ -229,8 +229,8 @@ static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst, struct wlantest_sta *sta; const struct ieee802_1x_hdr *eapol; const struct wpa_eapol_key *hdr; - const u8 *key_data, *kck; - size_t kck_len; + const u8 *key_data, *kck, *mic; + size_t kck_len, mic_len; u16 key_info, key_data_len; struct wpa_eapol_ie_parse ie; @@ -245,6 +245,8 @@ static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst, eapol = (const struct ieee802_1x_hdr *) data; hdr = (const struct wpa_eapol_key *) (eapol + 1); + mic_len = wpa_mic_len(sta->key_mgmt); + mic = (const u8 *) (hdr + 1); if (is_zero(hdr->key_nonce, WPA_NONCE_LEN)) { add_note(wt, MSG_INFO, "EAPOL-Key 2/4 from " MACSTR " used zero nonce", MAC2STR(src)); @@ -255,7 +257,7 @@ static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst, } os_memcpy(sta->snonce, hdr->key_nonce, WPA_NONCE_LEN); key_info = WPA_GET_BE16(hdr->key_info); - key_data_len = WPA_GET_BE16(hdr->key_data_length); + key_data_len = WPA_GET_BE16(mic + mic_len); derive_ptk(wt, bss, sta, key_info & WPA_KEY_INFO_TYPE_MASK, data, len); if (!sta->ptk_set && !sta->tptk_set) { @@ -279,7 +281,7 @@ static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst, } add_note(wt, MSG_DEBUG, "Valid MIC found in EAPOL-Key 2/4"); - key_data = (const u8 *) (hdr + 1); + key_data = mic + mic_len + 2; if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0) { add_note(wt, MSG_INFO, "Failed to parse EAPOL-Key Key Data"); @@ -348,10 +350,10 @@ static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst, static u8 * decrypt_eapol_key_data_rc4(struct wlantest *wt, const u8 *kek, const struct wpa_eapol_key *hdr, + const u8 *keydata, u16 keydatalen, size_t *len) { u8 ek[32], *buf; - u16 keydatalen = WPA_GET_BE16(hdr->key_data_length); buf = os_malloc(keydatalen); if (buf == NULL) @@ -359,7 +361,7 @@ static u8 * decrypt_eapol_key_data_rc4(struct wlantest *wt, const u8 *kek, os_memcpy(ek, hdr->key_iv, 16); os_memcpy(ek + 16, kek, 16); - os_memcpy(buf, hdr + 1, keydatalen); + os_memcpy(buf, keydata, keydatalen); if (rc4_skip(ek, 32, 256, buf, keydatalen)) { add_note(wt, MSG_INFO, "RC4 failed"); os_free(buf); @@ -373,10 +375,10 @@ static u8 * decrypt_eapol_key_data_rc4(struct wlantest *wt, const u8 *kek, static u8 * decrypt_eapol_key_data_aes(struct wlantest *wt, const u8 *kek, const struct wpa_eapol_key *hdr, + const u8 *keydata, u16 keydatalen, size_t *len) { u8 *buf; - u16 keydatalen = WPA_GET_BE16(hdr->key_data_length); if (keydatalen % 8) { add_note(wt, MSG_INFO, "Unsupported AES-WRAP len %d", @@ -387,7 +389,7 @@ static u8 * decrypt_eapol_key_data_aes(struct wlantest *wt, const u8 *kek, buf = os_malloc(keydatalen); if (buf == NULL) return NULL; - if (aes_unwrap(kek, 16, keydatalen / 8, (u8 *) (hdr + 1), buf)) { + if (aes_unwrap(kek, 16, keydatalen / 8, keydata, buf)) { os_free(buf); add_note(wt, MSG_INFO, "AES unwrap failed - could not decrypt EAPOL-Key " @@ -400,22 +402,35 @@ static u8 * decrypt_eapol_key_data_aes(struct wlantest *wt, const u8 *kek, } -static u8 * decrypt_eapol_key_data(struct wlantest *wt, const u8 *kek, +static u8 * decrypt_eapol_key_data(struct wlantest *wt, int akmp, const u8 *kek, size_t kek_len, u16 ver, const struct wpa_eapol_key *hdr, size_t *len) { + size_t mic_len; + u16 keydatalen; + const u8 *mic, *keydata; + if (kek_len != 16) return NULL; + + mic = (const u8 *) (hdr + 1); + mic_len = wpa_mic_len(akmp); + keydata = mic + mic_len + 2; + keydatalen = WPA_GET_BE16(mic + mic_len); + switch (ver) { case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4: - return decrypt_eapol_key_data_rc4(wt, kek, hdr, len); + return decrypt_eapol_key_data_rc4(wt, kek, hdr, keydata, + keydatalen, len); case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES: case WPA_KEY_INFO_TYPE_AES_128_CMAC: - return decrypt_eapol_key_data_aes(wt, kek, hdr, len); + return decrypt_eapol_key_data_aes(wt, kek, hdr, keydata, + keydatalen, len); case WPA_KEY_INFO_TYPE_AKM_DEFINED: /* For now, assume this is OSEN */ - return decrypt_eapol_key_data_aes(wt, kek, hdr, len); + return decrypt_eapol_key_data_aes(wt, kek, hdr, keydata, + keydatalen, len); default: add_note(wt, MSG_INFO, "Unsupported EAPOL-Key Key Descriptor Version %u", @@ -544,8 +559,8 @@ static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst, struct wlantest_sta *sta; const struct ieee802_1x_hdr *eapol; const struct wpa_eapol_key *hdr; - const u8 *key_data, *kck, *kek; - size_t kck_len, kek_len; + const u8 *key_data, *kck, *kek, *mic; + size_t kck_len, kek_len, mic_len; int recalc = 0; u16 key_info, ver; u8 *decrypted_buf = NULL; @@ -561,9 +576,11 @@ static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst, sta = sta_get(bss, dst); if (sta == NULL) return; + mic_len = wpa_mic_len(sta->key_mgmt); eapol = (const struct ieee802_1x_hdr *) data; hdr = (const struct wpa_eapol_key *) (eapol + 1); + mic = (const u8 *) (hdr + 1); key_info = WPA_GET_BE16(hdr->key_info); if (os_memcmp(sta->anonce, hdr->key_nonce, WPA_NONCE_LEN) != 0) { @@ -602,16 +619,17 @@ static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst, } add_note(wt, MSG_DEBUG, "Valid MIC found in EAPOL-Key 3/4"); - key_data = (const u8 *) (hdr + 1); + key_data = mic + mic_len + 2; if (!(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { if (sta->proto & WPA_PROTO_RSN) add_note(wt, MSG_INFO, "EAPOL-Key 3/4 without EncrKeyData bit"); decrypted = key_data; - decrypted_len = WPA_GET_BE16(hdr->key_data_length); + decrypted_len = WPA_GET_BE16(mic + mic_len); } else { ver = key_info & WPA_KEY_INFO_TYPE_MASK; - decrypted_buf = decrypt_eapol_key_data(wt, kek, kek_len, ver, + decrypted_buf = decrypt_eapol_key_data(wt, sta->key_mgmt, + kek, kek_len, ver, hdr, &decrypted_len); if (decrypted_buf == NULL) { add_note(wt, MSG_INFO, @@ -653,11 +671,12 @@ static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst, pos += 8; os_memcpy(pos, eapol, sizeof(*eapol)); pos += sizeof(*eapol); - os_memcpy(pos, hdr, sizeof(*hdr)); + os_memcpy(pos, hdr, sizeof(*hdr) + mic_len); k = (struct wpa_eapol_key *) pos; + pos += sizeof(struct wpa_eapol_key) + mic_len; WPA_PUT_BE16(k->key_info, key_info & ~WPA_KEY_INFO_ENCR_KEY_DATA); - WPA_PUT_BE16(k->key_data_length, plain_len); + WPA_PUT_BE16(pos, plain_len); write_pcap_decrypted(wt, buf, sizeof(buf), decrypted, plain_len); } @@ -770,6 +789,7 @@ static void rx_data_eapol_key_1_of_2(struct wlantest *wt, const u8 *dst, u16 key_info, ver; u8 *decrypted; size_t decrypted_len = 0; + size_t mic_len; wpa_printf(MSG_DEBUG, "EAPOL-Key 1/2 " MACSTR " -> " MACSTR, MAC2STR(src), MAC2STR(dst)); @@ -779,6 +799,7 @@ static void rx_data_eapol_key_1_of_2(struct wlantest *wt, const u8 *dst, sta = sta_get(bss, dst); if (sta == NULL) return; + mic_len = wpa_mic_len(sta->key_mgmt); eapol = (const struct ieee802_1x_hdr *) data; hdr = (const struct wpa_eapol_key *) (eapol + 1); @@ -805,7 +826,8 @@ static void rx_data_eapol_key_1_of_2(struct wlantest *wt, const u8 *dst, return; } ver = key_info & WPA_KEY_INFO_TYPE_MASK; - decrypted = decrypt_eapol_key_data(wt, sta->ptk.kek, sta->ptk.kek_len, + decrypted = decrypt_eapol_key_data(wt, sta->key_mgmt, + sta->ptk.kek, sta->ptk.kek_len, ver, hdr, &decrypted_len); if (decrypted == NULL) { add_note(wt, MSG_INFO, "Failed to decrypt EAPOL-Key Key Data"); @@ -843,11 +865,12 @@ static void rx_data_eapol_key_1_of_2(struct wlantest *wt, const u8 *dst, pos += 8; os_memcpy(pos, eapol, sizeof(*eapol)); pos += sizeof(*eapol); - os_memcpy(pos, hdr, sizeof(*hdr)); + os_memcpy(pos, hdr, sizeof(*hdr) + mic_len); k = (struct wpa_eapol_key *) pos; + pos += sizeof(struct wpa_eapol_key) + mic_len; WPA_PUT_BE16(k->key_info, key_info & ~WPA_KEY_INFO_ENCR_KEY_DATA); - WPA_PUT_BE16(k->key_data_length, plain_len); + WPA_PUT_BE16(pos, plain_len); write_pcap_decrypted(wt, buf, sizeof(buf), decrypted, plain_len); } @@ -926,7 +949,8 @@ static void rx_data_eapol_key_2_of_2(struct wlantest *wt, const u8 *dst, } -static void rx_data_eapol_key(struct wlantest *wt, const u8 *dst, +static void rx_data_eapol_key(struct wlantest *wt, const u8 *bssid, + const u8 *sta_addr, const u8 *dst, const u8 *src, const u8 *data, size_t len, int prot) { @@ -934,17 +958,29 @@ static void rx_data_eapol_key(struct wlantest *wt, const u8 *dst, const struct wpa_eapol_key *hdr; const u8 *key_data; u16 key_info, key_length, ver, key_data_length; + size_t mic_len = 16; + const u8 *mic; + struct wlantest_bss *bss; + struct wlantest_sta *sta; + + bss = bss_get(wt, bssid); + if (bss) { + sta = sta_get(bss, sta_addr); + if (sta) + mic_len = wpa_mic_len(sta->key_mgmt); + } eapol = (const struct ieee802_1x_hdr *) data; hdr = (const struct wpa_eapol_key *) (eapol + 1); wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key", (const u8 *) hdr, len - sizeof(*eapol)); - if (len < sizeof(*hdr)) { + if (len < sizeof(*hdr) + mic_len + 2) { add_note(wt, MSG_INFO, "Too short EAPOL-Key frame from " MACSTR, MAC2STR(src)); return; } + mic = (const u8 *) (hdr + 1); if (hdr->type == EAPOL_KEY_TYPE_RC4) { /* TODO: EAPOL-Key RC4 for WEP */ @@ -962,8 +998,8 @@ static void rx_data_eapol_key(struct wlantest *wt, const u8 *dst, key_info = WPA_GET_BE16(hdr->key_info); key_length = WPA_GET_BE16(hdr->key_length); - key_data_length = WPA_GET_BE16(hdr->key_data_length); - key_data = (const u8 *) (hdr + 1); + key_data_length = WPA_GET_BE16(mic + mic_len); + key_data = mic + mic_len + 2; if (key_data + key_data_length > data + len) { add_note(wt, MSG_INFO, "Truncated EAPOL-Key from " MACSTR, MAC2STR(src)); @@ -1010,7 +1046,7 @@ static void rx_data_eapol_key(struct wlantest *wt, const u8 *dst, wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key RSC", hdr->key_rsc, WPA_KEY_RSC_LEN); wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key MIC", - hdr->key_mic, 16); + mic, mic_len); wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data", key_data, key_data_length); @@ -1120,7 +1156,8 @@ static void rx_data_eapol_key(struct wlantest *wt, const u8 *dst, } -void rx_data_eapol(struct wlantest *wt, const u8 *dst, const u8 *src, +void rx_data_eapol(struct wlantest *wt, const u8 *bssid, const u8 *sta_addr, + const u8 *dst, const u8 *src, const u8 *data, size_t len, int prot) { const struct ieee802_1x_hdr *hdr; @@ -1167,8 +1204,8 @@ void rx_data_eapol(struct wlantest *wt, const u8 *dst, const u8 *src, wpa_hexdump(MSG_MSGDUMP, "EAPOL-Logoff", p, length); break; case IEEE802_1X_TYPE_EAPOL_KEY: - rx_data_eapol_key(wt, dst, src, data, sizeof(*hdr) + length, - prot); + rx_data_eapol_key(wt, bssid, sta_addr, dst, src, data, + sizeof(*hdr) + length, prot); break; case IEEE802_1X_TYPE_EAPOL_ENCAPSULATED_ASF_ALERT: wpa_hexdump(MSG_MSGDUMP, "EAPOL - Encapsulated ASF alert", diff --git a/wlantest/wlantest.h b/wlantest/wlantest.h index 0de04c692..f9a67c32f 100644 --- a/wlantest/wlantest.h +++ b/wlantest/wlantest.h @@ -243,7 +243,8 @@ void monitor_deinit(struct wlantest *wt); void rx_mgmt(struct wlantest *wt, const u8 *data, size_t len); void rx_mgmt_ack(struct wlantest *wt, const struct ieee80211_hdr *hdr); void rx_data(struct wlantest *wt, const u8 *data, size_t len); -void rx_data_eapol(struct wlantest *wt, const u8 *dst, const u8 *src, +void rx_data_eapol(struct wlantest *wt, const u8 *bssid, const u8 *sta_addr, + const u8 *dst, const u8 *src, const u8 *data, size_t len, int prot); void rx_data_ip(struct wlantest *wt, const u8 *bssid, const u8 *sta_addr, const u8 *dst, const u8 *src, const u8 *data, size_t len, -- 2.39.5