]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
wlantest: Add replay detection for CCMP
authorJouni Malinen <j@w1.fi>
Thu, 11 Nov 2010 18:21:11 +0000 (20:21 +0200)
committerJouni Malinen <j@w1.fi>
Thu, 11 Nov 2010 18:21:11 +0000 (20:21 +0200)
wlantest/ccmp.c
wlantest/rx_data.c
wlantest/wlantest.h

index c6da41ad3dd0e3e9aa045a70bb03423c3ffcf8d6..7bb2d2e2af17b5a9cf5f7f9ac6b90267d421684a 100644 (file)
@@ -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 */
+}
index 95d6b1663b395dd0cea45ae852d328bd950e1150..13d2fc3643d70db81082e827d22dc7e311da793e 100644 (file)
@@ -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);
 }
 
index a1fd39260f7b67a8872c65e80c2fddd1ab769d6a..5a7ec9e9c29bea1b50556291a51083d31a8fbc10 100644 (file)
@@ -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 */