diff --git a/monitor/nlmon.c b/monitor/nlmon.c index 1dc3cd67..8f0572f0 100644 --- a/monitor/nlmon.c +++ b/monitor/nlmon.c @@ -3839,7 +3839,7 @@ static void print_attributes(int indent, const struct attr_entry *table, static void print_eapol_key(const void *data, uint32_t size) { - const struct eapol_key *ek = eapol_key_validate(data, size); + const struct eapol_key *ek = eapol_key_validate(data, size, 16); if (!ek) return; @@ -3872,16 +3872,16 @@ static void print_eapol_key(const void *data, uint32_t size) print_attr(1, "Key RSC "); print_hexdump(2, ek->key_rsc, 8); print_attr(1, "Key MIC Data"); - print_hexdump(2, ek->key_mic_data, 16); + print_hexdump(2, EAPOL_KEY_MIC(ek), 16); if (ek->encrypted_key_data) { - print_attr(1, "Key Data: len %d", - L_BE16_TO_CPU(ek->key_data_len)); - print_hexdump(2, ek->key_data, L_BE16_TO_CPU(ek->key_data_len)); + print_attr(1, "Key Data: len %d", EAPOL_KEY_DATA_LEN(ek, 16)); + print_hexdump(2, EAPOL_KEY_DATA(ek, 16), + EAPOL_KEY_DATA_LEN(ek, 16)); return; } - print_ie(1, "Key Data", ek->key_data, L_BE16_TO_CPU(ek->key_data_len)); + print_ie(1, "Key Data", ek->key_data, EAPOL_KEY_DATA_LEN(ek, 16)); } static void netlink_str(char *str, size_t size, diff --git a/src/eapol.c b/src/eapol.c index a93eada1..faa02991 100644 --- a/src/eapol.c +++ b/src/eapol.c @@ -56,36 +56,38 @@ uint32_t next_frame_watch_id; return false; \ } while (false) \ +#define MIC_MAXLEN 32 + /* * MIC calculation depends on the selected hash function. The has function * is given in the EAPoL Key Descriptor Version field. * - * The MIC length is always 16 bytes for currently known Key Descriptor - * Versions. - * * The input struct eapol_key *frame should have a zero-d MIC field */ bool eapol_calculate_mic(enum ie_rsn_akm_suite akm, const uint8_t *kck, - const struct eapol_key *frame, uint8_t *mic) + const struct eapol_key *frame, uint8_t *mic, + size_t mic_len) { - size_t frame_len = sizeof(struct eapol_key); - - frame_len += L_BE16_TO_CPU(frame->key_data_len); + size_t frame_len = EAPOL_FRAME_LEN(mic_len) + + EAPOL_KEY_DATA_LEN(frame, mic_len); switch (frame->key_descriptor_version) { case EAPOL_KEY_DESCRIPTOR_VERSION_HMAC_MD5_ARC4: - return hmac_md5(kck, 16, frame, frame_len, mic, 16); + return hmac_md5(kck, 16, frame, frame_len, mic, mic_len); case EAPOL_KEY_DESCRIPTOR_VERSION_HMAC_SHA1_AES: - return hmac_sha1(kck, 16, frame, frame_len, mic, 16); + return hmac_sha1(kck, 16, frame, frame_len, mic, mic_len); case EAPOL_KEY_DESCRIPTOR_VERSION_AES_128_CMAC_AES: - return cmac_aes(kck, 16, frame, frame_len, mic, 16); + return cmac_aes(kck, 16, frame, frame_len, mic, mic_len); case EAPOL_KEY_DESCRIPTOR_VERSION_AKM_DEFINED: switch (akm) { case IE_RSN_AKM_SUITE_SAE_SHA256: case IE_RSN_AKM_SUITE_FT_OVER_SAE_SHA256: - return cmac_aes(kck, 16, frame, frame_len, mic, 16); + return cmac_aes(kck, 16, frame, frame_len, + mic, mic_len); case IE_RSN_AKM_SUITE_OWE: - return hmac_sha256(kck, 16, frame, frame_len, mic, 16); + return hmac_sha256(kck, mic_len, frame, + frame_len, mic, + mic_len); default: return false; } @@ -95,24 +97,21 @@ bool eapol_calculate_mic(enum ie_rsn_akm_suite akm, const uint8_t *kck, } bool eapol_verify_mic(enum ie_rsn_akm_suite akm, const uint8_t *kck, - const struct eapol_key *frame) + const struct eapol_key *frame, size_t mic_len) { - size_t frame_len = sizeof(struct eapol_key); - uint8_t mic[16]; + uint8_t mic[MIC_MAXLEN]; struct iovec iov[3]; struct l_checksum *checksum = NULL; iov[0].iov_base = (void *) frame; - iov[0].iov_len = offsetof(struct eapol_key, key_mic_data); + iov[0].iov_len = offsetof(struct eapol_key, key_data); memset(mic, 0, sizeof(mic)); iov[1].iov_base = mic; - iov[1].iov_len = sizeof(mic); + iov[1].iov_len = mic_len; - iov[2].iov_base = ((void *) frame) + - offsetof(struct eapol_key, key_data_len); - iov[2].iov_len = frame_len - offsetof(struct eapol_key, key_data_len) + - L_BE16_TO_CPU(frame->key_data_len); + iov[2].iov_base = (void *) EAPOL_KEY_DATA(frame, mic_len) - 2; + iov[2].iov_len = EAPOL_KEY_DATA_LEN(frame, mic_len) + 2; switch (frame->key_descriptor_version) { case EAPOL_KEY_DESCRIPTOR_VERSION_HMAC_MD5_ARC4: @@ -147,21 +146,35 @@ bool eapol_verify_mic(enum ie_rsn_akm_suite akm, const uint8_t *kck, return false; l_checksum_updatev(checksum, iov, 3); - l_checksum_get_digest(checksum, mic, 16); + l_checksum_get_digest(checksum, mic, mic_len); l_checksum_free(checksum); - if (!memcmp(frame->key_mic_data, mic, 16)) + if (!memcmp(frame->key_data, mic, mic_len)) return true; return false; } +/* + * IEEE 802.11 Table 12-8 -- Integrity and key-wrap algorithms + */ +static size_t eapol_get_mic_length(enum ie_rsn_akm_suite akm) +{ + switch (akm) { + case IE_RSN_AKM_SUITE_8021X_SUITE_B_SHA384: + case IE_RSN_AKM_SUITE_FT_OVER_8021X_SHA384: + return 24; + default: + return 16; + } +} + uint8_t *eapol_decrypt_key_data(enum ie_rsn_akm_suite akm, const uint8_t *kek, const struct eapol_key *frame, - size_t *decrypted_size) + size_t *decrypted_size, size_t mic_len) { - size_t key_data_len = L_BE16_TO_CPU(frame->key_data_len); - const uint8_t *key_data = frame->key_data; + size_t key_data_len = EAPOL_KEY_DATA_LEN(frame, mic_len); + const uint8_t *key_data = EAPOL_KEY_DATA(frame, mic_len); size_t expected_len; uint8_t *buf; @@ -239,7 +252,7 @@ error: */ static bool eapol_encrypt_key_data(const uint8_t *kek, uint8_t *key_data, size_t key_data_len, - struct eapol_key *out_frame) + struct eapol_key *out_frame, size_t mic_len) { switch (out_frame->key_descriptor_version) { case EAPOL_KEY_DESCRIPTOR_VERSION_HMAC_MD5_ARC4: @@ -253,7 +266,8 @@ static bool eapol_encrypt_key_data(const uint8_t *kek, uint8_t *key_data, while (key_data_len < 16 || key_data_len % 8) key_data[key_data_len++] = 0x00; - if (!aes_wrap(kek, key_data, key_data_len, out_frame->key_data)) + if (!aes_wrap(kek, key_data, key_data_len, + EAPOL_KEY_DATA(out_frame, mic_len))) return false; key_data_len += 8; @@ -261,26 +275,26 @@ static bool eapol_encrypt_key_data(const uint8_t *kek, uint8_t *key_data, break; } - out_frame->key_data_len = L_CPU_TO_BE16(key_data_len); + l_put_be16(key_data_len, EAPOL_KEY_DATA(out_frame, mic_len) - 2); return true; } static void eapol_key_data_append(struct eapol_key *ek, + size_t mic_len, enum handshake_kde selector, const uint8_t *data, size_t data_len) { - uint16_t key_data_len = L_BE16_TO_CPU(ek->key_data_len); + uint16_t key_data_len = EAPOL_KEY_DATA_LEN(ek, mic_len); + uint8_t *ptr = EAPOL_KEY_DATA(ek, mic_len); - ek->key_data[key_data_len++] = IE_TYPE_VENDOR_SPECIFIC; - ek->key_data[key_data_len++] = 4 + data_len; /* OUI + Data type + len */ - l_put_be32(selector, ek->key_data + key_data_len); + ptr[key_data_len++] = IE_TYPE_VENDOR_SPECIFIC; + ptr[key_data_len++] = 4 + data_len; + l_put_be32(selector, ptr + key_data_len); key_data_len += 4; - - memcpy(ek->key_data + key_data_len, data, data_len); + memcpy(ptr + key_data_len, data, data_len); key_data_len += data_len; - - ek->key_data_len = L_CPU_TO_BE16(key_data_len); + l_put_be16(key_data_len, ek->key_data + mic_len); } #define VERIFY_PTK_COMMON(ek) \ @@ -293,7 +307,7 @@ static void eapol_key_data_append(struct eapol_key *ek, if (ek->error) \ return false \ -bool eapol_verify_ptk_1_of_4(const struct eapol_key *ek) +bool eapol_verify_ptk_1_of_4(const struct eapol_key *ek, size_t mic_len) { /* Verify according to 802.11, Section 11.6.6.2 */ VERIFY_PTK_COMMON(ek); @@ -318,7 +332,9 @@ bool eapol_verify_ptk_1_of_4(const struct eapol_key *ek) VERIFY_IS_ZERO(ek->key_rsc); VERIFY_IS_ZERO(ek->reserved); - VERIFY_IS_ZERO(ek->key_mic_data); + + if (!util_mem_is_zero(EAPOL_KEY_MIC(ek), mic_len)) + return false; return true; } @@ -545,9 +561,11 @@ static struct eapol_key *eapol_create_common( size_t extra_len, const uint8_t *extra_data, int key_type, - bool is_wpa) + bool is_wpa, + size_t mic_len) { - size_t to_alloc = sizeof(struct eapol_key); + size_t to_alloc = EAPOL_FRAME_LEN(mic_len); + struct eapol_key *out_frame = l_malloc(to_alloc + extra_len); memset(out_frame, 0, to_alloc + extra_len); @@ -571,9 +589,11 @@ static struct eapol_key *eapol_create_common( out_frame->key_replay_counter = L_CPU_TO_BE64(key_replay_counter); memcpy(out_frame->key_nonce, snonce, sizeof(out_frame->key_nonce)); - out_frame->key_data_len = L_CPU_TO_BE16(extra_len); + l_put_be16(extra_len, out_frame->key_data + mic_len); + if (extra_len) - memcpy(out_frame->key_data, extra_data, extra_len); + memcpy(EAPOL_KEY_DATA(out_frame, mic_len), extra_data, + extra_len); return out_frame; } @@ -585,18 +605,20 @@ struct eapol_key *eapol_create_ptk_2_of_4( const uint8_t snonce[], size_t extra_len, const uint8_t *extra_data, - bool is_wpa) + bool is_wpa, + size_t mic_len) { return eapol_create_common(protocol, version, false, key_replay_counter, snonce, extra_len, extra_data, 1, - is_wpa); + is_wpa, mic_len); } struct eapol_key *eapol_create_ptk_4_of_4( enum eapol_protocol_version protocol, enum eapol_key_descriptor_version version, uint64_t key_replay_counter, - bool is_wpa) + bool is_wpa, + size_t mic_len) { uint8_t snonce[32]; @@ -604,14 +626,14 @@ struct eapol_key *eapol_create_ptk_4_of_4( return eapol_create_common(protocol, version, is_wpa ? false : true, key_replay_counter, snonce, 0, NULL, - 1, is_wpa); + 1, is_wpa, mic_len); } struct eapol_key *eapol_create_gtk_2_of_2( enum eapol_protocol_version protocol, enum eapol_key_descriptor_version version, uint64_t key_replay_counter, - bool is_wpa, uint8_t wpa_key_id) + bool is_wpa, uint8_t wpa_key_id, size_t mic_len) { uint8_t snonce[32]; struct eapol_key *step2; @@ -619,7 +641,7 @@ struct eapol_key *eapol_create_gtk_2_of_2( memset(snonce, 0, sizeof(snonce)); step2 = eapol_create_common(protocol, version, true, key_replay_counter, snonce, 0, NULL, - 0, is_wpa); + 0, is_wpa, mic_len); if (!step2) return step2; @@ -694,6 +716,7 @@ struct eapol_sm { uint8_t installed_gtk[CRYPTO_MAX_GTK_LEN]; uint8_t installed_igtk_len; uint8_t installed_igtk[CRYPTO_MAX_IGTK_LEN]; + unsigned int mic_len; }; static void eapol_sm_destroy(void *value) @@ -892,7 +915,7 @@ static void eapol_send_ptk_1_of_4(struct eapol_sm *sm) sm->replay_counter++; - memset(ek, 0, sizeof(struct eapol_key)); + memset(ek, 0, EAPOL_FRAME_LEN(sm->mic_len)); ek->header.protocol_version = sm->protocol_version; ek->header.packet_type = 0x3; ek->descriptor_type = EAPOL_DESCRIPTOR_TYPE_80211; @@ -907,10 +930,11 @@ static void eapol_send_ptk_1_of_4(struct eapol_sm *sm) /* Write the PMKID KDE into Key Data field unencrypted */ crypto_derive_pmkid(sm->handshake->pmk, sm->handshake->spa, aa, pmkid, false); - eapol_key_data_append(ek, HANDSHAKE_KDE_PMKID, pmkid, 16); - ek->header.packet_len = L_CPU_TO_BE16(sizeof(struct eapol_key) + - L_BE16_TO_CPU(ek->key_data_len) - 4); + eapol_key_data_append(ek, sm->mic_len, HANDSHAKE_KDE_PMKID, pmkid, 16); + + ek->header.packet_len = L_CPU_TO_BE16(EAPOL_FRAME_LEN(sm->mic_len) + + EAPOL_KEY_DATA_LEN(ek, sm->mic_len) - 4); l_debug("STA: "MAC" retries=%u", MAC_STR(sm->handshake->spa), sm->frame_retry); @@ -938,7 +962,7 @@ static void eapol_handle_ptk_1_of_4(struct eapol_sm *sm, { const struct crypto_ptk *ptk; struct eapol_key *step2; - uint8_t mic[16]; + uint8_t mic[MIC_MAXLEN]; uint8_t *ies; size_t ies_len; const uint8_t *own_ie = sm->handshake->supplicant_ie; @@ -947,11 +971,11 @@ static void eapol_handle_ptk_1_of_4(struct eapol_sm *sm, l_debug("ifindex=%u", sm->handshake->ifindex); - if (!eapol_verify_ptk_1_of_4(ek)) + if (!eapol_verify_ptk_1_of_4(ek, sm->mic_len)) goto error_unspecified; - pmkid = handshake_util_find_pmkid_kde(ek->key_data, - L_BE16_TO_CPU(ek->key_data_len)); + pmkid = handshake_util_find_pmkid_kde(EAPOL_KEY_DATA(ek, sm->mic_len), + EAPOL_KEY_DATA_LEN(ek, sm->mic_len)); ie_parse_rsne_from_data(own_ie, own_ie[1] + 2, &rsn_info); @@ -1058,12 +1082,12 @@ static void eapol_handle_ptk_1_of_4(struct eapol_sm *sm, ek->key_descriptor_version, L_BE64_TO_CPU(ek->key_replay_counter), sm->handshake->snonce, ies_len, ies, - sm->handshake->wpa_ie); + sm->handshake->wpa_ie, sm->mic_len); ptk = handshake_state_get_ptk(sm->handshake); if (!eapol_calculate_mic(sm->handshake->akm_suite, ptk->kck, - step2, mic)) { + step2, mic, sm->mic_len)) { l_info("MIC calculation failed. " "Ensure Kernel Crypto is available."); l_free(step2); @@ -1072,7 +1096,7 @@ static void eapol_handle_ptk_1_of_4(struct eapol_sm *sm, return; } - memcpy(step2->key_mic_data, mic, sizeof(mic)); + memcpy(EAPOL_KEY_MIC(step2), mic, sm->mic_len); eapol_sm_write(sm, (struct eapol_frame *) step2, false); l_free(step2); @@ -1105,7 +1129,7 @@ static void eapol_send_ptk_3_of_4(struct eapol_sm *sm) sm->replay_counter++; - memset(ek, 0, sizeof(struct eapol_key)); + memset(ek, 0, EAPOL_FRAME_LEN(sm->mic_len)); ek->header.protocol_version = sm->protocol_version; ek->header.packet_type = 0x3; ek->descriptor_type = EAPOL_DESCRIPTOR_TYPE_80211; @@ -1151,15 +1175,16 @@ static void eapol_send_ptk_3_of_4(struct eapol_sm *sm) } if (!eapol_encrypt_key_data(ptk->kek, key_data_buf, - key_data_len, ek)) + key_data_len, ek, sm->mic_len)) return; - key_data_len = L_BE16_TO_CPU(ek->key_data_len); - ek->header.packet_len = L_CPU_TO_BE16(sizeof(struct eapol_key) + - key_data_len - 4); + key_data_len = EAPOL_KEY_DATA_LEN(ek, sm->mic_len); + + ek->header.packet_len = L_CPU_TO_BE16(EAPOL_FRAME_LEN(sm->mic_len) + + key_data_len - 4); if (!eapol_calculate_mic(sm->handshake->akm_suite, ptk->kck, ek, - ek->key_mic_data)) + EAPOL_KEY_MIC(ek), sm->mic_len)) return; l_debug("STA: "MAC" retries=%u", MAC_STR(sm->handshake->spa), @@ -1239,15 +1264,16 @@ static void eapol_handle_ptk_2_of_4(struct eapol_sm *sm, ek->key_nonce, ptk, ptk_size, false)) return; - if (!eapol_verify_mic(sm->handshake->akm_suite, ptk->kck, ek)) + if (!eapol_verify_mic(sm->handshake->akm_suite, ptk->kck, ek, + sm->mic_len)) return; /* * 12.7.6.3 b) 2) "the Authenticator checks that the RSNE bitwise * matches that from the (Re)Association Request frame. */ - rsne = eapol_find_rsne(ek->key_data, - L_BE16_TO_CPU(ek->key_data_len), NULL); + rsne = eapol_find_rsne(EAPOL_KEY_DATA(ek, sm->mic_len), + EAPOL_KEY_DATA_LEN(ek, sm->mic_len), NULL); if (!rsne || rsne[1] != sm->handshake->supplicant_ie[1] || memcmp(rsne + 2, sm->handshake->supplicant_ie + 2, rsne[1])) { @@ -1292,7 +1318,7 @@ static void eapol_handle_ptk_3_of_4(struct eapol_sm *sm, { const struct crypto_ptk *ptk; struct eapol_key *step4; - uint8_t mic[16]; + uint8_t mic[MIC_MAXLEN]; const uint8_t *gtk = NULL; size_t gtk_len; const uint8_t *igtk = NULL; @@ -1488,18 +1514,18 @@ retransmit: step4 = eapol_create_ptk_4_of_4(sm->protocol_version, ek->key_descriptor_version, sm->replay_counter, - sm->handshake->wpa_ie); + sm->handshake->wpa_ie, sm->mic_len); ptk = handshake_state_get_ptk(sm->handshake); if (!eapol_calculate_mic(sm->handshake->akm_suite, ptk->kck, - step4, mic)) { + step4, mic, sm->mic_len)) { l_free(step4); handshake_failed(sm, MMPDU_REASON_CODE_UNSPECIFIED); return; } - memcpy(step4->key_mic_data, mic, sizeof(mic)); + memcpy(EAPOL_KEY_MIC(step4), mic, sm->mic_len); eapol_sm_write(sm, (struct eapol_frame *) step4, false); l_free(step4); @@ -1550,7 +1576,8 @@ static void eapol_handle_ptk_4_of_4(struct eapol_sm *sm, if (L_BE64_TO_CPU(ek->key_replay_counter) != sm->replay_counter) return; - if (!eapol_verify_mic(sm->handshake->akm_suite, ptk->kck, ek)) + if (!eapol_verify_mic(sm->handshake->akm_suite, ptk->kck, ek, + sm->mic_len)) return; l_timeout_remove(sm->timeout); @@ -1566,7 +1593,7 @@ static void eapol_handle_gtk_1_of_2(struct eapol_sm *sm, { const struct crypto_ptk *ptk; struct eapol_key *step2; - uint8_t mic[16]; + uint8_t mic[MIC_MAXLEN]; const uint8_t *gtk; size_t gtk_len; uint8_t gtk_key_index; @@ -1634,18 +1661,19 @@ static void eapol_handle_gtk_1_of_2(struct eapol_sm *sm, step2 = eapol_create_gtk_2_of_2(sm->protocol_version, ek->key_descriptor_version, sm->replay_counter, - sm->handshake->wpa_ie, ek->wpa_key_id); + sm->handshake->wpa_ie, ek->wpa_key_id, + sm->mic_len); ptk = handshake_state_get_ptk(sm->handshake); if (!eapol_calculate_mic(sm->handshake->akm_suite, ptk->kck, - step2, mic)) { + step2, mic, sm->mic_len)) { l_free(step2); handshake_failed(sm, MMPDU_REASON_CODE_UNSPECIFIED); return; } - memcpy(step2->key_mic_data, mic, sizeof(mic)); + memcpy(EAPOL_KEY_MIC(step2), mic, sm->mic_len); eapol_sm_write(sm, (struct eapol_frame *) step2, false); l_free(step2); @@ -1687,7 +1715,8 @@ static void eapol_key_handle(struct eapol_sm *sm, ek = eapol_key_validate((const uint8_t *) frame, sizeof(struct eapol_header) + - L_BE16_TO_CPU(frame->header.packet_len)); + L_BE16_TO_CPU(frame->header.packet_len), + sm->mic_len); if (!ek) return; @@ -1739,7 +1768,8 @@ static void eapol_key_handle(struct eapol_sm *sm, if (!sm->handshake->have_snonce) return; - if (!eapol_verify_mic(sm->handshake->akm_suite, ptk->kck, ek)) + if (!eapol_verify_mic(sm->handshake->akm_suite, ptk->kck, ek, + sm->mic_len)) return; } @@ -1751,11 +1781,11 @@ static void eapol_key_handle(struct eapol_sm *sm, decrypted_key_data = eapol_decrypt_key_data( sm->handshake->akm_suite, ptk->kek, - ek, &key_data_len); + ek, &key_data_len, sm->mic_len); if (!decrypted_key_data) return; } else - key_data_len = L_BE16_TO_CPU(ek->key_data_len); + key_data_len = EAPOL_KEY_DATA_LEN(ek, sm->mic_len); if (ek->key_type == 0) { /* GTK handshake allowed only after PTK handshake complete */ @@ -1782,7 +1812,8 @@ static void eapol_key_handle(struct eapol_sm *sm, goto done; eapol_handle_ptk_3_of_4(sm, ek, - decrypted_key_data ?: ek->key_data, + decrypted_key_data ?: + EAPOL_KEY_DATA(ek, sm->mic_len), key_data_len); } @@ -1869,6 +1900,21 @@ static void eapol_eap_results_cb(const uint8_t *msk_data, size_t msk_len, if (msk_len > sizeof(sm->handshake->pmk)) msk_len = sizeof(sm->handshake->pmk); + sm->mic_len = eapol_get_mic_length(sm->handshake->akm_suite); + + switch (sm->handshake->akm_suite) { + case IE_RSN_AKM_SUITE_FT_OVER_8021X: + msk_len = 64; + break; + case IE_RSN_AKM_SUITE_8021X_SUITE_B_SHA384: + case IE_RSN_AKM_SUITE_FT_OVER_8021X_SHA384: + msk_len = 48; + break; + default: + msk_len = 32; + break; + } + handshake_state_set_pmk(sm->handshake, msk_data, msk_len); return; @@ -1909,7 +1955,7 @@ static void eapol_auth_key_handle(struct eapol_sm *sm, { size_t frame_len = 4 + L_BE16_TO_CPU(frame->header.packet_len); const struct eapol_key *ek = eapol_key_validate((const void *) frame, - frame_len); + frame_len, sm->mic_len); if (!ek) return; @@ -2069,6 +2115,8 @@ void eapol_register(struct eapol_sm *sm) eapol_rx_auth_packet, sm); sm->started = true; + /* Since AP/AdHoc only support AKM PSK we can hard code this */ + sm->mic_len = 16; /* kick off handshake */ eapol_ptk_1_of_4_retry(NULL, sm); @@ -2112,6 +2160,8 @@ bool eapol_start(struct eapol_sm *sm) l_timeout_create(1, send_eapol_start, sm, NULL); } + sm->mic_len = eapol_get_mic_length(sm->handshake->akm_suite); + /* Process any frames received early due to scheduling */ if (sm->early_frame) { eapol_rx_packet(ETH_P_PAE, sm->handshake->aa, diff --git a/src/eapol.h b/src/eapol.h index dd0e9b0d..2306048e 100644 --- a/src/eapol.h +++ b/src/eapol.h @@ -52,15 +52,16 @@ typedef void (*eapol_frame_watch_func_t)(uint16_t proto, const uint8_t *from, void *user_data); bool eapol_calculate_mic(enum ie_rsn_akm_suite akm, const uint8_t *kck, - const struct eapol_key *frame, uint8_t *mic); + const struct eapol_key *frame, uint8_t *mic, + size_t mic_len); bool eapol_verify_mic(enum ie_rsn_akm_suite akm, const uint8_t *kck, - const struct eapol_key *frame); + const struct eapol_key *frame, size_t mic_len); uint8_t *eapol_decrypt_key_data(enum ie_rsn_akm_suite akm, const uint8_t *kek, const struct eapol_key *frame, - size_t *decrypted_size); + size_t *decrypted_size, size_t mic_len); -bool eapol_verify_ptk_1_of_4(const struct eapol_key *ek); +bool eapol_verify_ptk_1_of_4(const struct eapol_key *ek, size_t mic_len); bool eapol_verify_ptk_2_of_4(const struct eapol_key *ek); bool eapol_verify_ptk_3_of_4(const struct eapol_key *ek, bool is_wpa); bool eapol_verify_ptk_4_of_4(const struct eapol_key *ek, bool is_wpa); @@ -74,19 +75,22 @@ struct eapol_key *eapol_create_ptk_2_of_4( const uint8_t snonce[], size_t extra_len, const uint8_t *extra_data, - bool is_wpa); + bool is_wpa, + size_t mic_len); struct eapol_key *eapol_create_ptk_4_of_4( enum eapol_protocol_version protocol, enum eapol_key_descriptor_version version, uint64_t key_replay_counter, - bool is_wpa); + bool is_wpa, + size_t mic_len); struct eapol_key *eapol_create_gtk_2_of_2( enum eapol_protocol_version protocol, enum eapol_key_descriptor_version version, uint64_t key_replay_counter, - bool is_wpa, uint8_t wpa_key_id); + bool is_wpa, uint8_t wpa_key_id, + size_t mic_len); void __eapol_rx_packet(uint32_t ifindex, const uint8_t *src, uint16_t proto, const uint8_t *frame, size_t len, bool noencrypt); diff --git a/src/eapolutil.c b/src/eapolutil.c index 36500d78..fbf3ea8c 100644 --- a/src/eapolutil.c +++ b/src/eapolutil.c @@ -29,16 +29,24 @@ #include "src/eapolutil.h" -const struct eapol_key *eapol_key_validate(const uint8_t *frame, size_t len) +const struct eapol_key *eapol_key_validate(const uint8_t *frame, size_t len, + size_t mic_len) { const struct eapol_key *ek; - uint16_t key_data_len; - if (len < sizeof(struct eapol_key)) + /* + * Since EAPOL_KEY_DATA_LEN actually gets the key data length bytes we + * have to check this first, otherwise we could potentially overrun the + * frame buffer + */ + if (len < EAPOL_FRAME_LEN(mic_len)) return NULL; ek = (const struct eapol_key *) frame; + if (len < EAPOL_FRAME_LEN(mic_len) + EAPOL_KEY_DATA_LEN(ek, mic_len)) + return NULL; + switch (ek->header.protocol_version) { case EAPOL_PROTOCOL_VERSION_2001: case EAPOL_PROTOCOL_VERSION_2004: @@ -69,9 +77,5 @@ const struct eapol_key *eapol_key_validate(const uint8_t *frame, size_t len) return NULL; } - key_data_len = L_BE16_TO_CPU(ek->key_data_len); - if (len < sizeof(struct eapol_key) + key_data_len) - return NULL; - return ek; } diff --git a/src/eapolutil.h b/src/eapolutil.h index f8e00748..26ae50fd 100644 --- a/src/eapolutil.h +++ b/src/eapolutil.h @@ -59,6 +59,18 @@ struct eapol_frame { uint8_t data[0]; } __attribute__ ((packed)); +/* gets pointer to MIC */ +#define EAPOL_KEY_MIC(ek) ((ek)->key_data) + +/* get key data length */ +#define EAPOL_KEY_DATA_LEN(ek, mic_len) l_get_be16((ek)->key_data + (mic_len)) + +/* gets pointer to key data */ +#define EAPOL_KEY_DATA(ek, mic_len) ((ek)->key_data + (mic_len) + 2) + +/* gets frame length (not including key data) */ +#define EAPOL_FRAME_LEN(mic_len) sizeof(struct eapol_key) + (mic_len) + 2 + struct eapol_key { struct eapol_header header; uint8_t descriptor_type; @@ -98,9 +110,8 @@ struct eapol_key { uint8_t eapol_key_iv[16]; uint8_t key_rsc[8]; uint8_t reserved[8]; - uint8_t key_mic_data[16]; - __be16 key_data_len; uint8_t key_data[0]; } __attribute__ ((packed)); -const struct eapol_key *eapol_key_validate(const uint8_t *frame, size_t len); +const struct eapol_key *eapol_key_validate(const uint8_t *frame, size_t len, + size_t mic_len);