#include "common/ieee802_11_defs.h"
#include "wlantest.h"
+extern int wpa_debug_level;
+
static const char * data_stype(u16 stype)
{
}
+static u8 * try_all_ptk(struct wlantest *wt, int pairwise_cipher,
+ const struct ieee80211_hdr *hdr,
+ const u8 *data, size_t data_len, size_t *decrypted_len)
+{
+ struct wlantest_ptk *ptk;
+ u8 *decrypted;
+ int prev_level = wpa_debug_level;
+
+ wpa_debug_level = MSG_WARNING;
+ dl_list_for_each(ptk, &wt->ptk, struct wlantest_ptk, list) {
+ decrypted = NULL;
+ if ((pairwise_cipher == WPA_CIPHER_CCMP ||
+ pairwise_cipher == 0) && ptk->ptk_len == 48) {
+ decrypted = ccmp_decrypt(ptk->ptk.tk1, hdr, data,
+ data_len, decrypted_len);
+ }
+ if ((pairwise_cipher == WPA_CIPHER_TKIP ||
+ pairwise_cipher == 0) && ptk->ptk_len == 64) {
+ decrypted = tkip_decrypt(ptk->ptk.tk1, hdr, data,
+ data_len, decrypted_len);
+ }
+ if (decrypted) {
+ wpa_debug_level = prev_level;
+ add_note(wt, MSG_DEBUG, "Found PTK match from list of all known PTKs");
+ return decrypted;
+ }
+ }
+ wpa_debug_level = prev_level;
+
+ return NULL;
+}
+
+
static void rx_data_bss_prot_group(struct wlantest *wt,
const struct ieee80211_hdr *hdr,
const u8 *qos, const u8 *dst, const u8 *src,
u8 pn[6], *rsc;
struct wlantest_tdls *tdls = NULL, *found;
const u8 *tk = NULL;
+ int ptk_iter_done = 0;
+ int try_ptk_iter = 0;
if (hdr->addr1[0] & 0x01) {
rx_data_bss_prot_group(wt, hdr, qos, dst, src, data, len);
(!sta->ptk_set && sta->pairwise_cipher != WPA_CIPHER_WEP40)) &&
tk == NULL) {
add_note(wt, MSG_MSGDUMP, "No PTK known to decrypt the frame");
- return;
+ if (dl_list_empty(&wt->ptk))
+ return;
+ try_ptk_iter = 1;
}
if (len < 4) {
decrypted = tkip_decrypt(sta->ptk.tk1, hdr, data, len, &dlen);
else if (sta->pairwise_cipher == WPA_CIPHER_WEP40)
decrypted = wep_decrypt(wt, hdr, data, len, &dlen);
- else
+ else if (sta->ptk_set)
decrypted = ccmp_decrypt(sta->ptk.tk1, hdr, data, len, &dlen);
+ else {
+ decrypted = try_all_ptk(wt, sta->pairwise_cipher, hdr, data,
+ len, &dlen);
+ ptk_iter_done = 1;
+ }
+ if (!decrypted && !ptk_iter_done) {
+ decrypted = try_all_ptk(wt, sta->pairwise_cipher, hdr, data,
+ len, &dlen);
+ if (decrypted) {
+ add_note(wt, MSG_DEBUG, "Current PTK did not work, but found a match from all known PTKs");
+ }
+ }
if (decrypted) {
u16 fc = le_to_host16(hdr->frame_control);
const u8 *peer_addr = NULL;
dlen, 1, peer_addr);
write_pcap_decrypted(wt, (const u8 *) hdr, 24 + (qos ? 2 : 0),
decrypted, dlen);
- } else
+ } else if (!try_ptk_iter)
add_note(wt, MSG_DEBUG, "Failed to decrypt frame");
os_free(decrypted);
}
#include "rsn_supp/wpa_ie.h"
#include "wlantest.h"
+extern int wpa_debug_level;
+
static int is_zero(const u8 *buf, size_t len)
{
if (try_pmk(wt, bss, sta, ver, data, len, pmk) == 0)
return;
}
+
+ if (!sta->ptk_set) {
+ struct wlantest_ptk *ptk;
+ int prev_level = wpa_debug_level;
+
+ wpa_debug_level = MSG_WARNING;
+ dl_list_for_each(ptk, &wt->ptk, struct wlantest_ptk, list) {
+ if (check_mic(ptk->ptk.kck, ver, data, len) < 0)
+ continue;
+ wpa_printf(MSG_INFO, "Pre-set PTK matches for STA "
+ MACSTR " BSSID " MACSTR,
+ MAC2STR(sta->addr), MAC2STR(bss->bssid));
+ add_note(wt, MSG_DEBUG, "Using pre-set PTK");
+ os_memcpy(&sta->ptk, &ptk->ptk, sizeof(ptk->ptk));
+ wpa_hexdump(MSG_DEBUG, "PTK:KCK", sta->ptk.kck, 16);
+ wpa_hexdump(MSG_DEBUG, "PTK:KEK", sta->ptk.kek, 16);
+ wpa_hexdump(MSG_DEBUG, "PTK:TK1", sta->ptk.tk1, 16);
+ if (ptk->ptk_len > 48)
+ wpa_hexdump(MSG_DEBUG, "PTK:TK2",
+ sta->ptk.u.tk2, 16);
+ sta->ptk_set = 1;
+ os_memset(sta->rsc_tods, 0, sizeof(sta->rsc_tods));
+ os_memset(sta->rsc_fromds, 0, sizeof(sta->rsc_fromds));
+ }
+ wpa_debug_level = prev_level;
+ }
+
add_note(wt, MSG_DEBUG, "No matching PMK found to derive PTK");
}
"[-P<RADIUS shared secret>]\n"
" [-n<write pcapng file>]\n"
" [-w<write pcap file>] [-f<MSK/PMK file>]\n"
- " [-L<log file>]\n");
+ " [-L<log file>] [-T<PTK file>]\n");
}
dl_list_init(&wt->secret);
dl_list_init(&wt->radius);
dl_list_init(&wt->pmk);
+ dl_list_init(&wt->ptk);
dl_list_init(&wt->wep);
}
}
+static void ptk_deinit(struct wlantest_ptk *ptk)
+{
+ dl_list_del(&ptk->list);
+ os_free(ptk);
+}
+
+
static void wlantest_deinit(struct wlantest *wt)
{
struct wlantest_passphrase *p, *pn;
struct wlantest_radius_secret *s, *sn;
struct wlantest_radius *r, *rn;
struct wlantest_pmk *pmk, *np;
+ struct wlantest_ptk *ptk, *npt;
struct wlantest_wep *wep, *nw;
if (wt->ctrl_sock >= 0)
radius_deinit(r);
dl_list_for_each_safe(pmk, np, &wt->pmk, struct wlantest_pmk, list)
pmk_deinit(pmk);
+ dl_list_for_each_safe(ptk, npt, &wt->ptk, struct wlantest_ptk, list)
+ ptk_deinit(ptk);
dl_list_for_each_safe(wep, nw, &wt->wep, struct wlantest_wep, list)
os_free(wep);
write_pcap_deinit(wt);
}
+static int add_ptk_file(struct wlantest *wt, const char *ptk_file)
+{
+ FILE *f;
+ u8 ptk[64];
+ size_t ptk_len;
+ char buf[300], *pos;
+ struct wlantest_ptk *p;
+
+ f = fopen(ptk_file, "r");
+ if (f == NULL) {
+ wpa_printf(MSG_ERROR, "Could not open '%s'", ptk_file);
+ return -1;
+ }
+
+ while (fgets(buf, sizeof(buf), f)) {
+ pos = buf;
+ while (*pos && *pos != '\r' && *pos != '\n')
+ pos++;
+ *pos = '\0';
+ ptk_len = pos - buf;
+ if (ptk_len & 1)
+ continue;
+ ptk_len /= 2;
+ if (ptk_len != 16 && ptk_len != 32 &&
+ ptk_len != 48 && ptk_len != 64)
+ continue;
+ if (hexstr2bin(buf, ptk, ptk_len) < 0)
+ continue;
+ p = os_zalloc(sizeof(*p));
+ if (p == NULL)
+ break;
+ if (ptk_len < 48) {
+ os_memcpy(p->ptk.tk1, ptk, ptk_len);
+ p->ptk_len = 32 + ptk_len;
+ } else {
+ os_memcpy(&p->ptk, ptk, ptk_len);
+ p->ptk_len = ptk_len;
+ }
+ dl_list_add(&wt->ptk, &p->list);
+ wpa_hexdump(MSG_DEBUG, "Added PTK from file", ptk, ptk_len);
+ }
+
+ fclose(f);
+ return 0;
+}
+
+
int add_wep(struct wlantest *wt, const char *key)
{
struct wlantest_wep *w;
wlantest_init(&wt);
for (;;) {
- c = getopt(argc, argv, "cdf:Fhi:I:L:n:p:P:qr:R:tw:W:");
+ c = getopt(argc, argv, "cdf:Fhi:I:L:n:p:P:qr:R:tT:w:W:");
if (c < 0)
break;
switch (c) {
case 't':
wpa_debug_timestamp = 1;
break;
+ case 'T':
+ if (add_ptk_file(&wt, optarg) < 0)
+ return -1;
+ break;
case 'w':
wt.write_file = optarg;
break;
u8 pmk[32];
};
+struct wlantest_ptk {
+ struct dl_list list;
+ struct wpa_ptk ptk;
+ size_t ptk_len;
+};
+
struct wlantest_wep {
struct dl_list list;
size_t key_len;
struct dl_list secret; /* struct wlantest_radius_secret */
struct dl_list radius; /* struct wlantest_radius */
struct dl_list pmk; /* struct wlantest_pmk */
+ struct dl_list ptk; /* struct wlantest_ptk */
struct dl_list wep; /* struct wlantest_wep */
unsigned int rx_mgmt;