]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
wlantest: Learn GTK/IGTK/BIGTK for the current link in MLO case
authorJouni Malinen <quic_jouni@quicinc.com>
Wed, 28 Sep 2022 21:00:45 +0000 (00:00 +0300)
committerJouni Malinen <j@w1.fi>
Wed, 28 Sep 2022 21:00:45 +0000 (00:00 +0300)
Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
wlantest/rx_eapol.c

index a8f67881f2724d4416cdbe2ba498719d90df4523..ac80fb273ba3665495e22b5747db5f224652e3f0 100644 (file)
@@ -514,11 +514,120 @@ static u8 * decrypt_eapol_key_data(struct wlantest *wt, int akmp, const u8 *kek,
 }
 
 
+static void learn_kde_keys_mlo(struct wlantest *wt, struct wlantest_bss *bss,
+                              struct wlantest_sta *sta, int link_id,
+                              struct wpa_eapol_ie_parse *ie)
+{
+       const u8 *key, *pn;
+       size_t key_len;
+       unsigned int key_id;
+       bool tx;
+
+       if (ie->mlo_gtk[link_id]) {
+               pn = ie->mlo_gtk[link_id] + 1;
+               key = ie->mlo_gtk[link_id] + RSN_MLO_GTK_KDE_PREFIX_LENGTH;
+               key_len = ie->mlo_gtk_len[link_id] -
+                       RSN_MLO_GTK_KDE_PREFIX_LENGTH;
+               key_id = ie->mlo_gtk[link_id][0] &
+                       RSN_MLO_GTK_KDE_PREFIX0_KEY_ID_MASK;
+               tx = ie->mlo_gtk[link_id][0] & RSN_MLO_GTK_KDE_PREFIX0_TX;
+               if (key_len <= WPA_GTK_MAX_LEN) {
+                       add_note(wt, MSG_DEBUG, "GTK KeyID=%u tx=%u",
+                                key_id, tx);
+                       if (ie->mlo_gtk[link_id][0] & BIT(3)) {
+                               add_note(wt, MSG_INFO,
+                                        "MLO GTK KDE: Reserved field set");
+                       }
+                       wpa_hexdump(MSG_DEBUG, "GTK", key, key_len);
+                       bss->gtk_len[key_id] = key_len;
+                       sta->gtk_len = key_len;
+                       os_memcpy(bss->gtk[key_id], key, key_len);
+                       os_memcpy(sta->gtk, key, key_len);
+                       bss->rsc[key_id][0] = pn[5];
+                       bss->rsc[key_id][1] = pn[4];
+                       bss->rsc[key_id][2] = pn[3];
+                       bss->rsc[key_id][3] = pn[2];
+                       bss->rsc[key_id][4] = pn[1];
+                       bss->rsc[key_id][5] = pn[0];
+                       bss->gtk_idx = key_id;
+                       sta->gtk_idx = key_id;
+                       wpa_hexdump(MSG_DEBUG, "RSC", bss->rsc[key_id], 6);
+               } else {
+                       add_note(wt, MSG_INFO,
+                                "Invalid MLO GTK KDE key length %zu",
+                                key_len);
+               }
+       }
+
+       if (ie->mlo_igtk[link_id]) {
+               pn = ie->mlo_igtk[link_id] + 2;
+               key = ie->mlo_igtk[link_id] + RSN_MLO_IGTK_KDE_PREFIX_LENGTH;
+               key_len = ie->mlo_igtk_len[link_id] -
+                       RSN_MLO_IGTK_KDE_PREFIX_LENGTH;
+               key_id = WPA_GET_LE16(ie->mlo_igtk[link_id]);
+               if (key_len <= WPA_IGTK_MAX_LEN && key_id >= 4 && key_id <= 5) {
+                       add_note(wt, MSG_DEBUG, "IGTK KeyID=%u", key_id);
+                       if (ie->mlo_igtk[link_id][2 + 6] & 0x0f) {
+                               add_note(wt, MSG_INFO,
+                                        "MLO IGTK KDE: Reserved field set");
+                       }
+                       wpa_hexdump(MSG_DEBUG, "IGTK", key, key_len);
+                       wpa_hexdump(MSG_DEBUG, "IPN", pn, 6);
+                       bss->igtk_len[key_id] = key_len;
+                       os_memcpy(bss->igtk[key_id], key, key_len);
+                       bss->ipn[key_id][0] = pn[5];
+                       bss->ipn[key_id][1] = pn[4];
+                       bss->ipn[key_id][2] = pn[3];
+                       bss->ipn[key_id][3] = pn[2];
+                       bss->ipn[key_id][4] = pn[1];
+                       bss->ipn[key_id][5] = pn[0];
+                       bss->igtk_idx = key_id;
+               } else {
+                       add_note(wt, MSG_INFO,
+                                "Invalid MLO IGTK KDE ID %u or key length %zu",
+                                key_id, key_len);
+               }
+       }
+
+       if (ie->mlo_bigtk[link_id]) {
+               pn = ie->mlo_bigtk[link_id] + 2;
+               key = ie->mlo_bigtk[link_id] + RSN_MLO_BIGTK_KDE_PREFIX_LENGTH;
+               key_len = ie->mlo_bigtk_len[link_id] -
+                       RSN_MLO_BIGTK_KDE_PREFIX_LENGTH;
+               key_id = WPA_GET_LE16(ie->mlo_bigtk[link_id]);
+               if (key_len <= WPA_BIGTK_MAX_LEN &&
+                   key_id >= 6 && key_id <= 7) {
+                       add_note(wt, MSG_DEBUG, "BIGTK KeyID=%u", key_id);
+                       if (ie->mlo_bigtk[link_id][2 + 6] & 0x0f) {
+                               add_note(wt, MSG_INFO,
+                                        "MLO BIGTK KDE: Reserved field set");
+                       }
+                       wpa_hexdump(MSG_DEBUG, "BIGTK", key, key_len);
+                       wpa_hexdump(MSG_DEBUG, "BIPN", pn, 6);
+                       bss->igtk_len[key_id] = key_len;
+                       os_memcpy(bss->igtk[key_id], key, key_len);
+                       bss->ipn[key_id][0] = pn[5];
+                       bss->ipn[key_id][1] = pn[4];
+                       bss->ipn[key_id][2] = pn[3];
+                       bss->ipn[key_id][3] = pn[2];
+                       bss->ipn[key_id][4] = pn[1];
+                       bss->ipn[key_id][5] = pn[0];
+                       bss->bigtk_idx = key_id;
+               } else {
+                       add_note(wt, MSG_INFO,
+                                "Invalid MLO IGTK KDE ID %u or key length %zu",
+                                key_id, key_len);
+               }
+       }
+}
+
+
 static void learn_kde_keys(struct wlantest *wt, struct wlantest_bss *bss,
                           struct wlantest_sta *sta,
                           const u8 *buf, size_t len, const u8 *rsc)
 {
        struct wpa_eapol_ie_parse ie;
+       int link_id;
 
        if (wpa_parse_kde_ies(buf, len, &ie) < 0) {
                add_note(wt, MSG_INFO, "Failed to parse EAPOL-Key Key Data");
@@ -685,6 +794,21 @@ static void learn_kde_keys(struct wlantest *wt, struct wlantest_bss *bss,
                                 (unsigned) ie.bigtk_len);
                }
        }
+
+       for (link_id = 0; link_id < MAX_NUM_MLO_LINKS; link_id++) {
+               const u8 *addr;
+
+               if (!ie.mlo_link[link_id])
+                       continue;
+               addr = &ie.mlo_link[link_id][RSN_MLO_LINK_KDE_LINK_MAC_INDEX];
+               if (os_memcmp(addr, bss->bssid, ETH_ALEN) != 0)
+                       continue;
+               wpa_printf(MSG_DEBUG,
+                          "Trying to learn keys for the current MLO link (ID %u)",
+                          link_id);
+               learn_kde_keys_mlo(wt, bss, sta, link_id, &ie);
+               break;
+       }
 }