wlantest: Support TK list for Management frame decryption
Use the TKs from the PTK file (-T command line argument) to try to decrypt encrypted Management frames if no BSS/STA key can be found based on addresses. Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
fce6fb0ec2
commit
56a04ae1a1
4 changed files with 80 additions and 24 deletions
|
@ -119,19 +119,6 @@ static void rx_data_process(struct wlantest *wt, const u8 *bssid,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void write_decrypted_note(struct wlantest *wt, const u8 *decrypted,
|
|
||||||
const u8 *tk, size_t tk_len, int keyid)
|
|
||||||
{
|
|
||||||
char tk_hex[65];
|
|
||||||
|
|
||||||
if (!decrypted)
|
|
||||||
return;
|
|
||||||
|
|
||||||
wpa_snprintf_hex(tk_hex, sizeof(tk_hex), tk, tk_len);
|
|
||||||
add_note(wt, MSG_EXCESSIVE, "TK[%d] %s", keyid, tk_hex);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static u8 * try_ptk(int pairwise_cipher, struct wpa_ptk *ptk,
|
static u8 * try_ptk(int pairwise_cipher, struct wpa_ptk *ptk,
|
||||||
const struct ieee80211_hdr *hdr,
|
const struct ieee80211_hdr *hdr,
|
||||||
const u8 *data, size_t data_len, size_t *decrypted_len)
|
const u8 *data, size_t data_len, size_t *decrypted_len)
|
||||||
|
|
|
@ -2139,6 +2139,56 @@ static int check_bip(struct wlantest *wt, const u8 *data, size_t len)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static u8 * try_tk(struct wpa_ptk *ptk, const u8 *data, size_t len,
|
||||||
|
size_t *dlen)
|
||||||
|
{
|
||||||
|
const struct ieee80211_hdr *hdr;
|
||||||
|
u8 *decrypted, *frame;
|
||||||
|
|
||||||
|
hdr = (const struct ieee80211_hdr *) data;
|
||||||
|
decrypted = ccmp_decrypt(ptk->tk, hdr, data + 24, len - 24, dlen);
|
||||||
|
if (!decrypted)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
frame = os_malloc(24 + *dlen);
|
||||||
|
if (frame) {
|
||||||
|
os_memcpy(frame, data, 24);
|
||||||
|
os_memcpy(frame + 24, decrypted, *dlen);
|
||||||
|
*dlen += 24;
|
||||||
|
}
|
||||||
|
os_free(decrypted);
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static u8 * mgmt_ccmp_decrypt_tk(struct wlantest *wt, const u8 *data,
|
||||||
|
size_t len, size_t *dlen)
|
||||||
|
{
|
||||||
|
struct wlantest_ptk *ptk;
|
||||||
|
u8 *decrypted;
|
||||||
|
int prev_level = wpa_debug_level;
|
||||||
|
int keyid;
|
||||||
|
|
||||||
|
keyid = data[24 + 3] >> 6;
|
||||||
|
|
||||||
|
wpa_debug_level = MSG_WARNING;
|
||||||
|
dl_list_for_each(ptk, &wt->ptk, struct wlantest_ptk, list) {
|
||||||
|
decrypted = try_tk(&ptk->ptk, data, len, dlen);
|
||||||
|
if (decrypted) {
|
||||||
|
wpa_debug_level = prev_level;
|
||||||
|
add_note(wt, MSG_DEBUG,
|
||||||
|
"Found TK match from the list of all known TKs");
|
||||||
|
write_decrypted_note(wt, decrypted, ptk->ptk.tk,
|
||||||
|
ptk->ptk.tk_len, keyid);
|
||||||
|
return decrypted;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wpa_debug_level = prev_level;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static u8 * mgmt_ccmp_decrypt(struct wlantest *wt, const u8 *data, size_t len,
|
static u8 * mgmt_ccmp_decrypt(struct wlantest *wt, const u8 *data, size_t len,
|
||||||
size_t *dlen)
|
size_t *dlen)
|
||||||
{
|
{
|
||||||
|
@ -2150,17 +2200,6 @@ static u8 * mgmt_ccmp_decrypt(struct wlantest *wt, const u8 *data, size_t len,
|
||||||
u8 pn[6], *rsc;
|
u8 pn[6], *rsc;
|
||||||
|
|
||||||
hdr = (const struct ieee80211_hdr *) data;
|
hdr = (const struct ieee80211_hdr *) data;
|
||||||
bss = bss_get(wt, hdr->addr3);
|
|
||||||
if (bss == NULL)
|
|
||||||
return NULL;
|
|
||||||
if (os_memcmp(hdr->addr1, hdr->addr3, ETH_ALEN) == 0)
|
|
||||||
sta = sta_get(bss, hdr->addr2);
|
|
||||||
else
|
|
||||||
sta = sta_get(bss, hdr->addr1);
|
|
||||||
if (sta == NULL || !sta->ptk_set) {
|
|
||||||
add_note(wt, MSG_MSGDUMP, "No PTK known to decrypt the frame");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len < 24 + 4)
|
if (len < 24 + 4)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -2184,6 +2223,21 @@ static u8 * mgmt_ccmp_decrypt(struct wlantest *wt, const u8 *data, size_t len,
|
||||||
MACSTR, keyid, MAC2STR(hdr->addr2));
|
MACSTR, keyid, MAC2STR(hdr->addr2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bss = bss_get(wt, hdr->addr3);
|
||||||
|
if (bss == NULL)
|
||||||
|
return mgmt_ccmp_decrypt_tk(wt, data, len, dlen);
|
||||||
|
if (os_memcmp(hdr->addr1, hdr->addr3, ETH_ALEN) == 0)
|
||||||
|
sta = sta_get(bss, hdr->addr2);
|
||||||
|
else
|
||||||
|
sta = sta_get(bss, hdr->addr1);
|
||||||
|
if (sta == NULL || !sta->ptk_set) {
|
||||||
|
decrypted = mgmt_ccmp_decrypt_tk(wt, data, len, dlen);
|
||||||
|
if (!decrypted)
|
||||||
|
add_note(wt, MSG_MSGDUMP,
|
||||||
|
"No PTK known to decrypt the frame");
|
||||||
|
return decrypted;
|
||||||
|
}
|
||||||
|
|
||||||
if (os_memcmp(hdr->addr1, hdr->addr3, ETH_ALEN) == 0)
|
if (os_memcmp(hdr->addr1, hdr->addr3, ETH_ALEN) == 0)
|
||||||
rsc = sta->rsc_tods[16];
|
rsc = sta->rsc_tods[16];
|
||||||
else
|
else
|
||||||
|
|
|
@ -323,6 +323,19 @@ size_t notes_len(struct wlantest *wt, size_t hdrlen)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void write_decrypted_note(struct wlantest *wt, const u8 *decrypted,
|
||||||
|
const u8 *tk, size_t tk_len, int keyid)
|
||||||
|
{
|
||||||
|
char tk_hex[65];
|
||||||
|
|
||||||
|
if (!decrypted)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wpa_snprintf_hex(tk_hex, sizeof(tk_hex), tk, tk_len);
|
||||||
|
add_note(wt, MSG_EXCESSIVE, "TK[%d] %s", keyid, tk_hex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int wlantest_relog(struct wlantest *wt)
|
int wlantest_relog(struct wlantest *wt)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
|
@ -232,6 +232,8 @@ void add_note(struct wlantest *wt, int level, const char *fmt, ...)
|
||||||
PRINTF_FORMAT(3, 4);
|
PRINTF_FORMAT(3, 4);
|
||||||
void clear_notes(struct wlantest *wt);
|
void clear_notes(struct wlantest *wt);
|
||||||
size_t notes_len(struct wlantest *wt, size_t hdrlen);
|
size_t notes_len(struct wlantest *wt, size_t hdrlen);
|
||||||
|
void write_decrypted_note(struct wlantest *wt, const u8 *decrypted,
|
||||||
|
const u8 *tk, size_t tk_len, int keyid);
|
||||||
|
|
||||||
int add_wep(struct wlantest *wt, const char *key);
|
int add_wep(struct wlantest *wt, const char *key);
|
||||||
int read_cap_file(struct wlantest *wt, const char *fname);
|
int read_cap_file(struct wlantest *wt, const char *fname);
|
||||||
|
|
Loading…
Reference in a new issue