wlantest: Clone new PTK to all potentially matching STA entries for MLO

It is possible for there to be multiple STA entries (e.g., one for each
BSS) when a sniffer capture contains multiple associations using MLO.
For such cases, the new PTK information needs to be updated to all
existing STA entries to be able to find the latest TK when decrypting
following frames since the other STA entries might be located first when
trying to figure out how to decrypt a frame.

In addition to the PTK, copy the MLD MAC addresses to the other STA and
BSS entries to make sure the latest values are used when trying to
decrypt frames.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
This commit is contained in:
Jouni Malinen 2022-11-09 22:39:01 +02:00 committed by Jouni Malinen
parent 15583802b9
commit 153739b4ff
4 changed files with 64 additions and 18 deletions

View file

@ -248,14 +248,7 @@ static int try_pmk(struct wlantest *wt, struct wlantest_bss *bss,
sta->tptk_set = 1;
return 0;
}
add_note(wt, MSG_DEBUG, "Derived new PTK");
os_memcpy(&sta->ptk, &ptk, sizeof(ptk));
wpa_hexdump(MSG_DEBUG, "PTK:KCK", sta->ptk.kck, sta->ptk.kck_len);
wpa_hexdump(MSG_DEBUG, "PTK:KEK", sta->ptk.kek, sta->ptk.kek_len);
wpa_hexdump(MSG_DEBUG, "PTK:TK", sta->ptk.tk, sta->ptk.tk_len);
sta->ptk_set = 1;
os_memset(sta->rsc_tods, 0, sizeof(sta->rsc_tods));
os_memset(sta->rsc_fromds, 0, sizeof(sta->rsc_fromds));
sta_new_ptk(wt, sta, &ptk);
return 0;
}

View file

@ -298,11 +298,7 @@ static void process_ft_auth(struct wlantest *wt, struct wlantest_bss *bss,
sta->pairwise_cipher, 0) < 0)
return;
add_note(wt, MSG_DEBUG, "Derived new PTK");
os_memcpy(&sta->ptk, &ptk, sizeof(ptk));
sta->ptk_set = 1;
os_memset(sta->rsc_tods, 0, sizeof(sta->rsc_tods));
os_memset(sta->rsc_fromds, 0, sizeof(sta->rsc_fromds));
sta_new_ptk(wt, sta, &ptk);
}
@ -1823,11 +1819,7 @@ static void rx_mgmt_action_ft_response(struct wlantest *wt,
0) < 0)
return;
add_note(wt, MSG_DEBUG, "Derived new PTK");
os_memcpy(&new_sta->ptk, &ptk, sizeof(ptk));
new_sta->ptk_set = 1;
os_memset(new_sta->rsc_tods, 0, sizeof(new_sta->rsc_tods));
os_memset(new_sta->rsc_fromds, 0, sizeof(new_sta->rsc_fromds));
sta_new_ptk(wt, new_sta, &ptk);
os_memcpy(new_sta->snonce, parse.fte_snonce, WPA_NONCE_LEN);
os_memcpy(new_sta->anonce, parse.fte_anonce, WPA_NONCE_LEN);
}

View file

@ -272,3 +272,62 @@ skip_rsn_wpa:
sta->rsn_capab & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST ?
"ExtKeyID " : "");
}
static void sta_copy_ptk(struct wlantest_sta *sta, struct wpa_ptk *ptk)
{
os_memcpy(&sta->ptk, ptk, sizeof(*ptk));
sta->ptk_set = 1;
os_memset(sta->rsc_tods, 0, sizeof(sta->rsc_tods));
os_memset(sta->rsc_fromds, 0, sizeof(sta->rsc_fromds));
}
void sta_new_ptk(struct wlantest *wt, struct wlantest_sta *sta,
struct wpa_ptk *ptk)
{
struct wlantest_bss *bss;
struct wlantest_sta *osta;
add_note(wt, MSG_DEBUG, "Derived new PTK");
sta_copy_ptk(sta, ptk);
wpa_hexdump(MSG_DEBUG, "PTK:KCK", sta->ptk.kck, sta->ptk.kck_len);
wpa_hexdump(MSG_DEBUG, "PTK:KEK", sta->ptk.kek, sta->ptk.kek_len);
wpa_hexdump(MSG_DEBUG, "PTK:TK", sta->ptk.tk, sta->ptk.tk_len);
dl_list_for_each(bss, &wt->bss, struct wlantest_bss, list) {
dl_list_for_each(osta, &bss->sta, struct wlantest_sta, list) {
bool match = false;
int link_id;
if (osta == sta)
continue;
if (os_memcmp(sta->addr, osta->addr, ETH_ALEN) == 0)
match = true;
for (link_id = 0; !match && link_id < MAX_NUM_MLO_LINKS;
link_id++) {
if (os_memcmp(osta->link_addr[link_id],
sta->addr, ETH_ALEN) == 0)
match = true;
}
if (!match)
continue;
wpa_printf(MSG_DEBUG,
"Add PTK to another MLO STA entry " MACSTR
" (MLD " MACSTR " --> " MACSTR ") in BSS "
MACSTR " (MLD " MACSTR " --> " MACSTR ")",
MAC2STR(osta->addr),
MAC2STR(osta->mld_mac_addr),
MAC2STR(sta->mld_mac_addr),
MAC2STR(bss->bssid),
MAC2STR(bss->mld_mac_addr),
MAC2STR(sta->bss->mld_mac_addr));
sta_copy_ptk(osta, ptk);
os_memcpy(osta->mld_mac_addr, sta->mld_mac_addr,
ETH_ALEN);
os_memcpy(osta->bss->mld_mac_addr,
sta->bss->mld_mac_addr, ETH_ALEN);
}
}
}

View file

@ -306,6 +306,8 @@ struct wlantest_sta * sta_get(struct wlantest_bss *bss, const u8 *addr);
void sta_deinit(struct wlantest_sta *sta);
void sta_update_assoc(struct wlantest_sta *sta,
struct ieee802_11_elems *elems);
void sta_new_ptk(struct wlantest *wt, struct wlantest_sta *sta,
struct wpa_ptk *ptk);
u8 * ccmp_decrypt(const u8 *tk, const struct ieee80211_hdr *hdr,
const u8 *a1, const u8 *a2, const u8 *data, size_t data_len,