wlantest: Add replay detection for CCMP

master
Jouni Malinen 14 years ago
parent 07d0a5be45
commit 2edd5c23ad

@ -211,3 +211,14 @@ u8 * ccmp_decrypt(const u8 *tk, const struct ieee80211_hdr *hdr,
*decrypted_len = mlen;
return plain;
}
void ccmp_get_pn(u8 *pn, const u8 *data)
{
pn[0] = data[7]; /* PN5 */
pn[1] = data[6]; /* PN4 */
pn[2] = data[5]; /* PN3 */
pn[3] = data[4]; /* PN2 */
pn[4] = data[1]; /* PN1 */
pn[5] = data[0]; /* PN0 */
}

@ -136,6 +136,8 @@ static int try_pmk(struct wlantest_bss *bss, struct wlantest_sta *sta,
if (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));
return 0;
}
@ -287,7 +289,8 @@ static u8 * decrypt_eapol_key_data(const u8 *kek, u16 ver,
}
static void learn_kde_keys(struct wlantest_bss *bss, u8 *buf, size_t len)
static void learn_kde_keys(struct wlantest_bss *bss, u8 *buf, size_t len,
const u8 *rsc)
{
struct wpa_eapol_ie_parse ie;
@ -322,6 +325,13 @@ static void learn_kde_keys(struct wlantest_bss *bss, u8 *buf, size_t len)
ie.gtk_len - 2);
bss->gtk_len[id] = ie.gtk_len - 2;
os_memcpy(bss->gtk[id], ie.gtk + 2, ie.gtk_len - 2);
bss->rsc[id][0] = rsc[5];
bss->rsc[id][1] = rsc[4];
bss->rsc[id][2] = rsc[3];
bss->rsc[id][3] = rsc[2];
bss->rsc[id][4] = rsc[1];
bss->rsc[id][5] = rsc[0];
wpa_hexdump(MSG_DEBUG, "RSC", bss->rsc[id], 6);
} else {
wpa_printf(MSG_INFO, "Invalid GTK KDE length %u",
(unsigned) ie.gtk_len);
@ -418,7 +428,7 @@ static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst,
}
wpa_hexdump(MSG_DEBUG, "Decrypted EAPOL-Key Key Data",
decrypted, decrypted_len);
learn_kde_keys(bss, decrypted, decrypted_len);
learn_kde_keys(bss, decrypted, decrypted_len, hdr->key_rsc);
os_free(decrypted);
}
@ -555,7 +565,7 @@ static void rx_data_eapol_key(struct wlantest *wt, const u8 *dst,
wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key IV",
hdr->key_iv, 16);
wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key RSC",
hdr->key_nonce, WPA_KEY_RSC_LEN);
hdr->key_rsc, WPA_KEY_RSC_LEN);
wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key MIC",
hdr->key_mic, 16);
wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data",
@ -700,6 +710,7 @@ static void rx_data_bss_prot_group(struct wlantest *wt,
int keyid;
u8 *decrypted;
size_t dlen;
u8 pn[6];
bss = bss_get(wt, hdr->addr2);
if (bss == NULL)
@ -717,12 +728,21 @@ static void rx_data_bss_prot_group(struct wlantest *wt,
return;
}
/* TODO: check PN for replay */
ccmp_get_pn(pn, data);
if (os_memcmp(pn, bss->rsc[keyid], 6) <= 0) {
wpa_printf(MSG_INFO, "CCMP/TKIP replay detected: SA=" MACSTR,
MAC2STR(hdr->addr2));
wpa_hexdump(MSG_INFO, "RX PN", pn, 6);
wpa_hexdump(MSG_INFO, "RSC", bss->rsc[keyid], 6);
}
/* TODO: TKIP */
decrypted = ccmp_decrypt(bss->gtk[keyid], hdr, data, len, &dlen);
if (decrypted)
if (decrypted) {
rx_data_process(wt, dst, src, decrypted, dlen, 1);
os_memcpy(bss->rsc[keyid], pn, 6);
}
os_free(decrypted);
}
@ -738,6 +758,8 @@ static void rx_data_bss_prot(struct wlantest *wt,
u16 fc = le_to_host16(hdr->frame_control);
u8 *decrypted;
size_t dlen;
int tid;
u8 pn[6], *rsc;
if (hdr->addr1[0] & 0x01) {
rx_data_bss_prot_group(wt, hdr, qos, dst, src, data, len);
@ -772,12 +794,31 @@ static void rx_data_bss_prot(struct wlantest *wt,
keyid, MAC2STR(hdr->addr2));
}
/* TODO: check PN for replay */
if (qos)
tid = qos[0] & 0x0f;
else
tid = 0;
if (fc & WLAN_FC_TODS)
rsc = sta->rsc_tods[tid];
else
rsc = sta->rsc_fromds[tid];
ccmp_get_pn(pn, data);
if (os_memcmp(pn, rsc, 6) <= 0) {
wpa_printf(MSG_INFO, "CCMP/TKIP replay detected: SA=" MACSTR,
MAC2STR(hdr->addr2));
wpa_hexdump(MSG_INFO, "RX PN", pn, 6);
wpa_hexdump(MSG_INFO, "RSC", rsc, 6);
}
/* TODO: TKIP */
decrypted = ccmp_decrypt(sta->ptk.tk1, hdr, data, len, &dlen);
if (decrypted)
if (decrypted) {
rx_data_process(wt, dst, src, decrypted, dlen, 1);
os_memcpy(rsc, pn, 6);
}
os_free(decrypted);
}

@ -56,6 +56,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;
u8 rsc_tods[16][6];
u8 rsc_fromds[16][6];
};
struct wlantest_bss {
@ -72,6 +74,7 @@ struct wlantest_bss {
struct dl_list pmk; /* struct wlantest_pmk */
u8 gtk[4][32];
size_t gtk_len[4];
u8 rsc[4][6];
u8 igtk[6][16];
int igtk_set[6];
u8 ipn[6][6];
@ -124,5 +127,6 @@ void sta_update_assoc(struct wlantest_sta *sta,
u8 * ccmp_decrypt(const u8 *tk, const struct ieee80211_hdr *hdr,
const u8 *data, size_t data_len, size_t *decrypted_len);
void ccmp_get_pn(u8 *pn, const u8 *data);
#endif /* WLANTEST_H */

Loading…
Cancel
Save