]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
wlantest: Support TK list for Management frame decryption
authorJouni Malinen <j@w1.fi>
Sun, 7 Feb 2021 09:37:58 +0000 (11:37 +0200)
committerJouni Malinen <j@w1.fi>
Sun, 7 Feb 2021 09:37:58 +0000 (11:37 +0200)
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>
wlantest/rx_data.c
wlantest/rx_mgmt.c
wlantest/wlantest.c
wlantest/wlantest.h

index b632013a8534f58e8e91e8c2f003e8ae3799f81a..aedf9e824eb37a6a3b89dda9b637e5691e933050 100644 (file)
@@ -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,
                    const struct ieee80211_hdr *hdr,
                    const u8 *data, size_t data_len, size_t *decrypted_len)
index 61c7f6a4ce5beaaa1d9bd7d2b8090cadfc44faa7..2b05807529e5f2c992f95612a86d8ea4b25878cd 100644 (file)
@@ -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,
                              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;
 
        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)
                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));
        }
 
+       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)
                rsc = sta->rsc_tods[16];
        else
index 1b8d7147edbdb4d0286c3b0730ee4f098d7b32f2..62c89e2261502f283b96a1e185cb3795e6a2073d 100644 (file)
@@ -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 ret = 0;
index 0c266f4e95b159125fc6e74896e5e1bba05ffcc5..658a3a06d43b9c501691e5e714e18506e6bb3f4f 100644 (file)
@@ -232,6 +232,8 @@ void add_note(struct wlantest *wt, int level, const char *fmt, ...)
 PRINTF_FORMAT(3, 4);
 void clear_notes(struct wlantest *wt);
 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 read_cap_file(struct wlantest *wt, const char *fname);