]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
MLO: Validate MLO KDEs in EAPOL-Key msg 4/4
authorIlan Peer <ilan.peer@intel.com>
Mon, 22 May 2023 19:34:03 +0000 (22:34 +0300)
committerJouni Malinen <j@w1.fi>
Thu, 15 Jun 2023 14:32:31 +0000 (17:32 +0300)
Verify that the MLD address in EAPOL-Key msg 4/4 is set correctly for
MLO cases. Note that the mechanism used here for distinguishing between
EAPOL-Key msg 2/4 and 4/4 is not exactly ideal and should be improved in
the future.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
src/ap/wpa_auth.c

index c913f411d928029a485a186af8da10307298650f..a66fa2ccbeaa7dcb9792a852231c316b67a9a89a 100644 (file)
@@ -1077,9 +1077,15 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
        const u8 *key_data;
        size_t keyhdrlen, mic_len;
        u8 *mic;
+       bool is_mld = false;
 
        if (!wpa_auth || !wpa_auth->conf.wpa || !sm)
                return;
+
+#ifdef CONFIG_IEEE80211BE
+       is_mld = sm->mld_assoc_link_id >= 0;
+#endif /* CONFIG_IEEE80211BE */
+
        wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL data", data, data_len);
 
        mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
@@ -1149,6 +1155,11 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
                return;
        }
 
+       /* TODO: Make this more robust for distinguising EAPOL-Key msg 2/4 from
+        * 4/4. Secure=1 is used in msg 2/4 when doing PTK rekeying, so the
+        * MLD mechanism here does not work without the somewhat undesired check
+        * on wpa_ptk_state.. Would likely need to decrypt Key Data first to be
+        * able to know which message this is in MLO cases.. */
        if (key_info & WPA_KEY_INFO_REQUEST) {
                msg = REQUEST;
                msgtxt = "Request";
@@ -1157,7 +1168,9 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
                msgtxt = "2/2 Group";
        } else if (key_data_length == 0 ||
                   (mic_len == 0 && (key_info & WPA_KEY_INFO_ENCR_KEY_DATA) &&
-                   key_data_length == AES_BLOCK_SIZE)) {
+                   key_data_length == AES_BLOCK_SIZE) ||
+                  (is_mld && (key_info & WPA_KEY_INFO_SECURE) &&
+                   sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING)) {
                msg = PAIRWISE_4;
                msgtxt = "4/4 Pairwise";
        } else {
@@ -4317,10 +4330,68 @@ done:
 }
 
 
+static int wpa_auth_validate_ml_kdes_m4(struct wpa_state_machine *sm)
+{
+#ifdef CONFIG_IEEE80211BE
+       const struct ieee802_1x_hdr *hdr;
+       const struct wpa_eapol_key *key;
+       struct wpa_eapol_ie_parse kde;
+       const u8 *key_data, *mic;
+       u16 key_data_length;
+       size_t mic_len;
+
+       if (sm->mld_assoc_link_id < 0)
+               return 0;
+
+       /*
+        * Note: last_rx_eapol_key length fields have already been validated in
+        * wpa_receive().
+        */
+       mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
+
+       hdr = (const struct ieee802_1x_hdr *) sm->last_rx_eapol_key;
+       key = (const struct wpa_eapol_key *) (hdr + 1);
+       mic = (const u8 *) (key + 1);
+       key_data = mic + mic_len + 2;
+       key_data_length = WPA_GET_BE16(mic + mic_len);
+       if (key_data_length > sm->last_rx_eapol_key_len - sizeof(*hdr) -
+           sizeof(*key) - mic_len - 2)
+               return -1;
+
+       if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) {
+               wpa_auth_vlogger(sm->wpa_auth, wpa_auth_get_spa(sm),
+                                LOGGER_INFO,
+                                "received EAPOL-Key msg 4/4 with invalid Key Data contents");
+               return -1;
+       }
+
+       /* MLD MAC address must be the same */
+       if (!kde.mac_addr ||
+           os_memcmp(kde.mac_addr, sm->peer_mld_addr, ETH_ALEN) != 0) {
+               wpa_printf(MSG_DEBUG,
+                          "MLD: Mismatching or missing MLD address in EAPOL-Key msg 4/4");
+               return -1;
+       }
+
+       wpa_printf(MSG_DEBUG, "MLD: MLD address in EAPOL-Key msg 4/4: " MACSTR,
+                  MAC2STR(kde.mac_addr));
+#endif /* CONFIG_IEEE80211BE */
+
+       return 0;
+}
+
+
 SM_STATE(WPA_PTK, PTKINITDONE)
 {
        SM_ENTRY_MA(WPA_PTK, PTKINITDONE, wpa_ptk);
        sm->EAPOLKeyReceived = false;
+
+       if (wpa_auth_validate_ml_kdes_m4(sm) < 0) {
+               wpa_sta_disconnect(sm->wpa_auth, sm->addr,
+                                  WLAN_REASON_PREV_AUTH_NOT_VALID);
+               return;
+       }
+
        if (sm->Pair) {
                enum wpa_alg alg = wpa_cipher_to_alg(sm->pairwise);
                int klen = wpa_cipher_key_len(sm->pairwise);