diff --git a/wlantest/rx_data.c b/wlantest/rx_data.c index 36b045945..b7f1a896d 100644 --- a/wlantest/rx_data.c +++ b/wlantest/rx_data.c @@ -342,9 +342,9 @@ skip_replay_det: const u8 *peer_addr = NULL; if (!(fc & (WLAN_FC_FROMDS | WLAN_FC_TODS))) peer_addr = hdr->addr1; + os_memcpy(rsc, pn, 6); rx_data_process(wt, bss->bssid, sta->addr, dst, src, decrypted, dlen, 1, peer_addr); - os_memcpy(rsc, pn, 6); write_pcap_decrypted(wt, (const u8 *) hdr, 24 + (qos ? 2 : 0), decrypted, dlen); } diff --git a/wlantest/rx_eapol.c b/wlantest/rx_eapol.c index c7851b817..5a873268c 100644 --- a/wlantest/rx_eapol.c +++ b/wlantest/rx_eapol.c @@ -112,6 +112,21 @@ static int try_pmk(struct wlantest_bss *bss, struct wlantest_sta *sta, wpa_printf(MSG_INFO, "Derived PTK for STA " MACSTR " BSSID " MACSTR, MAC2STR(sta->addr), MAC2STR(bss->bssid)); sta->counters[WLANTEST_STA_COUNTER_PTK_LEARNED]++; + if (sta->ptk_set) { + /* + * Rekeying - use new PTK for EAPOL-Key frames, but continue + * using the old PTK for frame decryption. + */ + os_memcpy(&sta->tptk, &ptk, sizeof(ptk)); + wpa_hexdump(MSG_DEBUG, "TPTK:KCK", sta->tptk.kck, 16); + wpa_hexdump(MSG_DEBUG, "TPTK:KEK", sta->tptk.kek, 16); + wpa_hexdump(MSG_DEBUG, "TPTK:TK1", sta->tptk.tk1, 16); + if (ptk_len > 48) + wpa_hexdump(MSG_DEBUG, "TPTK:TK2", sta->tptk.u.tk2, + 16); + sta->tptk_set = 1; + return 0; + } os_memcpy(&sta->ptk, &ptk, sizeof(ptk)); wpa_hexdump(MSG_DEBUG, "PTK:KCK", sta->ptk.kck, 16); wpa_hexdump(MSG_DEBUG, "PTK:KEK", sta->ptk.kek, 16); @@ -155,7 +170,7 @@ 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; + const u8 *key_data, *kck; u16 key_info, key_data_len; struct wpa_eapol_ie_parse ie; @@ -183,13 +198,17 @@ static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst, key_data_len = WPA_GET_BE16(hdr->key_data_length); derive_ptk(wt, bss, sta, key_info & WPA_KEY_INFO_TYPE_MASK, data, len); - if (!sta->ptk_set) { + if (!sta->ptk_set && !sta->tptk_set) { wpa_printf(MSG_DEBUG, "No PTK known to process EAPOL-Key 2/4"); return; } - if (check_mic(sta->ptk.kck, key_info & WPA_KEY_INFO_TYPE_MASK, - data, len) < 0) { + kck = sta->ptk.kck; + if (sta->tptk_set) { + wpa_printf(MSG_DEBUG, "Use TPTK for validation EAPOL-Key MIC"); + kck = sta->tptk.kck; + } + if (check_mic(kck, key_info & WPA_KEY_INFO_TYPE_MASK, data, len) < 0) { wpa_printf(MSG_INFO, "Mismatch in EAPOL-Key 2/4 MIC"); return; } @@ -398,7 +417,7 @@ 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; + const u8 *key_data, *kck; int recalc = 0; u16 key_info, ver; u8 *decrypted_buf = NULL; @@ -430,13 +449,17 @@ static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst, data, len); } - if (!sta->ptk_set) { + if (!sta->ptk_set && !sta->tptk_set) { wpa_printf(MSG_DEBUG, "No PTK known to process EAPOL-Key 3/4"); return; } - if (check_mic(sta->ptk.kck, key_info & WPA_KEY_INFO_TYPE_MASK, - data, len) < 0) { + kck = sta->ptk.kck; + if (sta->tptk_set) { + wpa_printf(MSG_DEBUG, "Use TPTK for validation EAPOL-Key MIC"); + kck = sta->tptk.kck; + } + if (check_mic(kck, key_info & WPA_KEY_INFO_TYPE_MASK, data, len) < 0) { wpa_printf(MSG_INFO, "Mismatch in EAPOL-Key 3/4 MIC"); return; } @@ -549,6 +572,7 @@ static void rx_data_eapol_key_4_of_4(struct wlantest *wt, const u8 *dst, const struct ieee802_1x_hdr *eapol; const struct wpa_eapol_key *hdr; u16 key_info; + const u8 *kck; wpa_printf(MSG_DEBUG, "EAPOL-Key 4/4 " MACSTR " -> " MACSTR, MAC2STR(src), MAC2STR(dst)); @@ -567,18 +591,29 @@ static void rx_data_eapol_key_4_of_4(struct wlantest *wt, const u8 *dst, } key_info = WPA_GET_BE16(hdr->key_info); - if (!sta->ptk_set) { + if (!sta->ptk_set && !sta->tptk_set) { wpa_printf(MSG_DEBUG, "No PTK known to process EAPOL-Key 4/4"); return; } - if (sta->ptk_set && - check_mic(sta->ptk.kck, key_info & WPA_KEY_INFO_TYPE_MASK, - data, len) < 0) { + kck = sta->ptk.kck; + if (sta->tptk_set) { + wpa_printf(MSG_DEBUG, "Use TPTK for validation EAPOL-Key MIC"); + kck = sta->tptk.kck; + } + if (check_mic(kck, key_info & WPA_KEY_INFO_TYPE_MASK, data, len) < 0) { wpa_printf(MSG_INFO, "Mismatch in EAPOL-Key 4/4 MIC"); return; } wpa_printf(MSG_DEBUG, "Valid MIC found in EAPOL-Key 4/4"); + if (sta->tptk_set) { + wpa_printf(MSG_DEBUG, "Update PTK (rekeying)"); + os_memcpy(&sta->ptk, &sta->tptk, sizeof(sta->ptk)); + sta->ptk_set = 1; + sta->tptk_set = 0; + os_memset(sta->rsc_tods, 0, sizeof(sta->rsc_tods)); + os_memset(sta->rsc_fromds, 0, sizeof(sta->rsc_fromds)); + } } @@ -907,7 +942,12 @@ static void rx_data_eapol_key(struct wlantest *wt, const u8 *dst, rx_data_eapol_key_3_of_4(wt, dst, src, data, len); break; case WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC: - rx_data_eapol_key_4_of_4(wt, dst, src, data, len); + if (key_data_length == 0) + rx_data_eapol_key_4_of_4(wt, dst, src, data, + len); + else + rx_data_eapol_key_2_of_4(wt, dst, src, data, + len); break; default: wpa_printf(MSG_DEBUG, "Unsupported EAPOL-Key frame"); diff --git a/wlantest/wlantest.h b/wlantest/wlantest.h index a6165cce1..4c65d4839 100644 --- a/wlantest/wlantest.h +++ b/wlantest/wlantest.h @@ -70,6 +70,8 @@ struct wlantest_sta { u8 snonce[32]; /* SNonce from the previous EAPOL-Key msg 2/4 */ struct wpa_ptk ptk; /* Derived PTK */ int ptk_set; + struct wpa_ptk tptk; /* Derived PTK during rekeying */ + int tptk_set; u8 rsc_tods[16 + 1][6]; u8 rsc_fromds[16 + 1][6]; u8 ap_sa_query_tr[2];