]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
wlantest: BIGTK fetching and Beacon protection validation
authorJouni Malinen <jouni@codeaurora.org>
Fri, 21 Feb 2020 17:40:32 +0000 (19:40 +0200)
committerJouni Malinen <j@w1.fi>
Fri, 21 Feb 2020 17:41:36 +0000 (19:41 +0200)
Fetch the BIGTK from EAPOL-Key msg 3/4 and use it to validate MME in
Beacon frames when the AP uses Beacon protection.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
wlantest/rx_eapol.c
wlantest/rx_mgmt.c
wlantest/wlantest.h

index e184495423b45c99113c11aaa7d4bdedde34238c..e4fe7e23eb6ae35876ea993e19456ca0c9be1819 100644 (file)
@@ -548,6 +548,65 @@ static void learn_kde_keys(struct wlantest *wt, struct wlantest_bss *bss,
                                 (unsigned) ie.igtk_len);
                }
        }
+
+       if (ie.bigtk) {
+               wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data - BIGTK KDE",
+                           ie.bigtk, ie.bigtk_len);
+               if (ie.bigtk_len == 24) {
+                       u16 id;
+
+                       id = WPA_GET_LE16(ie.bigtk);
+                       if (id < 6 || id > 7) {
+                               add_note(wt, MSG_INFO,
+                                        "Unexpected BIGTK KeyID %u", id);
+                       } else {
+                               const u8 *ipn;
+
+                               add_note(wt, MSG_DEBUG, "BIGTK KeyID %u", id);
+                               wpa_hexdump(MSG_DEBUG, "BIPN", ie.bigtk + 2, 6);
+                               wpa_hexdump(MSG_DEBUG, "BIGTK", ie.bigtk + 8,
+                                           16);
+                               os_memcpy(bss->igtk[id], ie.bigtk + 8, 16);
+                               bss->igtk_len[id] = 16;
+                               ipn = ie.bigtk + 2;
+                               bss->ipn[id][0] = ipn[5];
+                               bss->ipn[id][1] = ipn[4];
+                               bss->ipn[id][2] = ipn[3];
+                               bss->ipn[id][3] = ipn[2];
+                               bss->ipn[id][4] = ipn[1];
+                               bss->ipn[id][5] = ipn[0];
+                               bss->bigtk_idx = id;
+                       }
+               } else if (ie.bigtk_len == 40) {
+                       u16 id;
+
+                       id = WPA_GET_LE16(ie.bigtk);
+                       if (id < 6 || id > 7) {
+                               add_note(wt, MSG_INFO,
+                                        "Unexpected BIGTK KeyID %u", id);
+                       } else {
+                               const u8 *ipn;
+
+                               add_note(wt, MSG_DEBUG, "BIGTK KeyID %u", id);
+                               wpa_hexdump(MSG_DEBUG, "BIPN", ie.bigtk + 2, 6);
+                               wpa_hexdump(MSG_DEBUG, "BIGTK", ie.bigtk + 8,
+                                           32);
+                               os_memcpy(bss->igtk[id], ie.bigtk + 8, 32);
+                               bss->igtk_len[id] = 32;
+                               ipn = ie.bigtk + 2;
+                               bss->ipn[id][0] = ipn[5];
+                               bss->ipn[id][1] = ipn[4];
+                               bss->ipn[id][2] = ipn[3];
+                               bss->ipn[id][3] = ipn[2];
+                               bss->ipn[id][4] = ipn[1];
+                               bss->ipn[id][5] = ipn[0];
+                               bss->bigtk_idx = id;
+                       }
+               } else {
+                       add_note(wt, MSG_INFO, "Invalid BIGTK KDE length %u",
+                                (unsigned) ie.bigtk_len);
+               }
+       }
 }
 
 
index 39b23b27ca683aa05d1c6da0752abc64033fc318..92762b8f04a81431f0dce41802f7ba0c0a286add 100644 (file)
 #include "wlantest.h"
 
 
+static int check_mmie_mic(unsigned int mgmt_group_cipher,
+                         const u8 *igtk, size_t igtk_len,
+                         const u8 *data, size_t len);
+
+
 static const char * mgmt_stype(u16 stype)
 {
        switch (stype) {
@@ -57,6 +62,9 @@ static void rx_mgmt_beacon(struct wlantest *wt, const u8 *data, size_t len)
        struct wlantest_bss *bss;
        struct ieee802_11_elems elems;
        size_t offset;
+       const u8 *mme;
+       size_t mic_len;
+       u16 keyid;
 
        mgmt = (const struct ieee80211_mgmt *) data;
        offset = mgmt->u.beacon.variable - data;
@@ -79,6 +87,62 @@ static void rx_mgmt_beacon(struct wlantest *wt, const u8 *data, size_t len)
        }
 
        bss_update(wt, bss, &elems);
+
+       mme = get_ie(mgmt->u.beacon.variable, len - offset, WLAN_EID_MMIE);
+       if (!mme) {
+               if (bss->bigtk_idx) {
+                       add_note(wt, MSG_INFO,
+                                "Unexpected unprotected Beacon frame from "
+                                MACSTR, MAC2STR(mgmt->sa));
+                       bss->counters[WLANTEST_BSS_COUNTER_MISSING_BIP_MMIE]++;
+               }
+               return;
+       }
+
+       mic_len = bss->mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC ? 8 : 16;
+       if (len < 24 + 10 + mic_len ||
+           data[len - (10 + mic_len)] != WLAN_EID_MMIE ||
+           data[len - (10 + mic_len - 1)] != 8 + mic_len) {
+               add_note(wt, MSG_INFO, "Invalid MME in a Beacon frame from "
+                        MACSTR, MAC2STR(mgmt->sa));
+               return;
+       }
+
+       mme += 2;
+       keyid = WPA_GET_LE16(mme);
+       if (keyid < 6 || keyid > 7) {
+               add_note(wt, MSG_INFO, "Unexpected MME KeyID %u from " MACSTR,
+                        keyid, MAC2STR(mgmt->sa));
+               bss->counters[WLANTEST_BSS_COUNTER_INVALID_BIP_MMIE]++;
+               return;
+       }
+
+       wpa_printf(MSG_DEBUG, "Beacon frame MME KeyID %u", keyid);
+       wpa_hexdump(MSG_MSGDUMP, "MME IPN", mme + 2, 6);
+       wpa_hexdump(MSG_MSGDUMP, "MME MIC", mme + 8, mic_len);
+
+       if (!bss->igtk_len[keyid]) {
+               add_note(wt, MSG_DEBUG, "No BIGTK known to validate BIP frame");
+               return;
+       }
+
+       if (os_memcmp(mme + 2, bss->ipn[keyid], 6) <= 0) {
+               add_note(wt, MSG_INFO, "BIP replay detected: SA=" MACSTR,
+                        MAC2STR(mgmt->sa));
+               wpa_hexdump(MSG_INFO, "RX IPN", mme + 2, 6);
+               wpa_hexdump(MSG_INFO, "Last RX IPN", bss->ipn[keyid], 6);
+       }
+
+       if (check_mmie_mic(bss->mgmt_group_cipher, bss->igtk[keyid],
+                          bss->igtk_len[keyid], data, len) < 0) {
+               add_note(wt, MSG_INFO, "Invalid MME MIC in a Beacon frame from "
+                        MACSTR, MAC2STR(mgmt->sa));
+               bss->counters[WLANTEST_BSS_COUNTER_INVALID_BIP_MMIE]++;
+               return;
+       }
+
+       add_note(wt, MSG_DEBUG, "Valid MME MIC in Beacon frame");
+       os_memcpy(bss->ipn[keyid], mme + 2, 6);
 }
 
 
@@ -1329,6 +1393,11 @@ static int check_mmie_mic(unsigned int mgmt_group_cipher,
        os_memcpy(buf + 20, data + 24, len - 24 - mic_len);
        os_memset(buf + 20 + len - 24 - mic_len, 0, mic_len);
 
+       if (WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON) {
+               /* Timestamp field masked to zero */
+               os_memset(buf + 20, 0, 8);
+       }
+
        wpa_hexdump(MSG_MSGDUMP, "BIP: AAD|Body(masked)", buf, len + 20 - 24);
        /* MIC = L(AES-128-CMAC(AAD || Frame Body(masked)), 0, 64) */
        if (mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) {
index 4f90b20e2a8f9985d71d4b3ccd33a29edddacab5..82eddc11c8587772184f1de65bc988f6ede00081 100644 (file)
@@ -150,10 +150,11 @@ struct wlantest_bss {
        size_t gtk_len[4];
        int gtk_idx;
        u8 rsc[4][6];
-       u8 igtk[6][32];
-       size_t igtk_len[6];
+       u8 igtk[8][32];
+       size_t igtk_len[8];
        int igtk_idx;
-       u8 ipn[6][6];
+       u8 ipn[8][6];
+       int bigtk_idx;
        u32 counters[NUM_WLANTEST_BSS_COUNTER];
        struct dl_list tdls; /* struct wlantest_tdls */
        u8 mdid[2];