]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
PASN: Include RSNXE in the PASN negotiation
authorIlan Peer <ilan.peer@intel.com>
Wed, 16 Dec 2020 11:01:38 +0000 (13:01 +0200)
committerJouni Malinen <j@w1.fi>
Tue, 26 Jan 2021 21:09:36 +0000 (23:09 +0200)
IEEE P802.11az/D2.6 added definitions to include RSNXE in the PASN
negotiation. Implement the new functionality in both wpa_supplicant and
hostapd.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
src/ap/beacon.c
src/ap/beacon.h
src/ap/ieee802_11.c
src/common/wpa_common.c
src/common/wpa_common.h
wpa_supplicant/pasn_supplicant.c
wpa_supplicant/wpa_supplicant_i.h

index 47b260e810e8e1e78a3f1f3c2b36978fd6193f3a..16f1e96c0a78f5b31af3681f5d1df146c2bde547 100644 (file)
@@ -266,7 +266,7 @@ static u8 * hostapd_eid_country(struct hostapd_data *hapd, u8 *eid,
 }
 
 
-static const u8 * hostapd_wpa_ie(struct hostapd_data *hapd, u8 eid)
+const u8 * hostapd_wpa_ie(struct hostapd_data *hapd, u8 eid)
 {
        const u8 *ies;
        size_t ies_len;
index a26e30879cf53e5ee56129e86f6e72cf2f3e07a1..c320825f3570c9a77400d61831221e9e1711c27a 100644 (file)
@@ -30,4 +30,6 @@ sta_track_seen_on(struct hostapd_iface *iface, const u8 *addr,
 void sta_track_claim_taxonomy_info(struct hostapd_iface *iface, const u8 *addr,
                                   struct wpabuf **probe_ie_taxonomy);
 
+const u8 * hostapd_wpa_ie(struct hostapd_data *hapd, u8 eid);
+
 #endif /* BEACON_H */
index f5b87fbf536d8f680a0cd157c59c3b4a8d68c933..daf73efb043e6e7e13972637451e8ccd190596b3 100644 (file)
@@ -2877,9 +2877,10 @@ static int handle_auth_pasn_resp(struct hostapd_data *hapd,
 {
        struct wpabuf *buf, *pubkey = NULL, *wrapped_data_buf = NULL;
        u8 mic[WPA_PASN_MAX_MIC_LEN];
-       u8 mic_len, data_len;
+       u8 mic_len, frame_len, data_len;
        u8 *ptr;
-       const u8 *data, *rsn_ie;
+       const u8 *frame, *data, *rsn_ie, *rsnxe_ie;
+       u8 *data_buf = NULL;
        size_t rsn_ie_len;
        int ret;
 
@@ -2926,6 +2927,11 @@ static int handle_auth_pasn_resp(struct hostapd_data *hapd,
        wpabuf_free(pubkey);
        pubkey = NULL;
 
+       /* Add RSNXE if needed */
+       rsnxe_ie = hostapd_wpa_ie(hapd, WLAN_EID_RSNX);
+       if (rsnxe_ie)
+               wpabuf_put_data(buf, rsnxe_ie, 2 + rsnxe_ie[1]);
+
        /* Add the mic */
        mic_len = pasn_mic_len(sta->pasn->akmp, sta->pasn->cipher);
        wpabuf_put_u8(buf, WLAN_EID_MIC);
@@ -2934,8 +2940,8 @@ static int handle_auth_pasn_resp(struct hostapd_data *hapd,
 
        os_memset(ptr, 0, mic_len);
 
-       data = wpabuf_head_u8(buf) + IEEE80211_HDRLEN;
-       data_len = wpabuf_len(buf) - IEEE80211_HDRLEN;
+       frame = wpabuf_head_u8(buf) + IEEE80211_HDRLEN;
+       frame_len = wpabuf_len(buf) - IEEE80211_HDRLEN;
 
        rsn_ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &rsn_ie_len);
        if (!rsn_ie || !rsn_ie_len)
@@ -2946,9 +2952,24 @@ static int handle_auth_pasn_resp(struct hostapd_data *hapd,
         * MDE, etc. Thus, do not use the returned length but instead use the
         * length specified in the IE header.
         */
+       data_len = rsn_ie[1] + 2;
+       if (rsnxe_ie) {
+               data_buf = os_zalloc(rsn_ie[1] + 2 + rsnxe_ie[1] + 2);
+               if (!data_buf)
+                       goto fail;
+
+               os_memcpy(data_buf, rsn_ie, rsn_ie[1] + 2);
+               os_memcpy(data_buf + rsn_ie[1] + 2, rsnxe_ie, rsnxe_ie[1] + 2);
+               data_len += rsnxe_ie[1] + 2;
+               data = data_buf;
+       } else {
+               data = rsn_ie;
+       }
+
        ret = pasn_mic(sta->pasn->ptk.kck, sta->pasn->akmp, sta->pasn->cipher,
-                      hapd->own_addr, sta->addr, rsn_ie, rsn_ie[1] + 2,
-                      data, data_len, mic);
+                      hapd->own_addr, sta->addr, data, data_len,
+                      frame, frame_len, mic);
+       os_free(data_buf);
        if (ret) {
                wpa_printf(MSG_DEBUG, "PASN: Frame 3: Failed MIC calculation");
                goto fail;
index a56b7631bc32b30beee0381fe52792b71b10709a..2b8c7f661e006106c682ca22dab5d167bc0e2f36 100644 (file)
@@ -1327,8 +1327,8 @@ u8 pasn_mic_len(int akmp, int cipher)
  * @addr2: For the 2nd PASN frame the BSSID; for the 3rd frame the supplicant
  *     address
  * @data: For calculating the MIC for the 2nd PASN frame, this should hold the
- *     Beacon frame RSNE. For calculating the MIC for the 3rd PASN frame, this
- *     should hold the hash of the body of the PASN 1st frame.
+ *     Beacon frame RSNE + RSNXE. For calculating the MIC for the 3rd PASN
+ *     frame, this should hold the hash of the body of the PASN 1st frame.
  * @data_len: The length of data
  * @frame: The body of the PASN frame including the MIC element with the octets
  *     in the MIC field of the MIC element set to 0.
@@ -3692,4 +3692,24 @@ int wpa_pasn_parse_parameter_ie(const u8 *data, u8 len, bool from_ap,
        return 0;
 }
 
+
+void wpa_pasn_add_rsnxe(struct wpabuf *buf, u16 capab)
+{
+       size_t flen;
+
+       flen = (capab & 0xff00) ? 2 : 1;
+       if (!capab)
+               return; /* no supported extended RSN capabilities */
+       if (wpabuf_tailroom(buf) < 2 + flen)
+               return;
+       capab |= flen - 1; /* bit 0-3 = Field length (n - 1) */
+
+       wpabuf_put_u8(buf, WLAN_EID_RSNX);
+       wpabuf_put_u8(buf, flen);
+       wpabuf_put_u8(buf, capab & 0x00ff);
+       capab >>= 8;
+       if (capab)
+               wpabuf_put_u8(buf, capab);
+}
+
 #endif /* CONFIG_PASN */
index 4fe8077a6a85a43a01c33122ec92358c87235f0e..c31e1a0fa58908a12ad171f2cf8d2cb74287a0a2 100644 (file)
@@ -21,6 +21,7 @@
 #define WPA_GTK_MAX_LEN 32
 #define WPA_PASN_PMK_LEN 32
 #define WPA_PASN_MAX_MIC_LEN 24
+#define WPA_MAX_RSNXE_LEN 4
 
 #define OWE_DH_GROUP 19
 
@@ -664,4 +665,6 @@ int wpa_pasn_validate_rsne(const struct wpa_ie_data *data);
 int wpa_pasn_parse_parameter_ie(const u8 *data, u8 len, bool from_ap,
                                struct wpa_pasn_params_data *pasn_params);
 
+void wpa_pasn_add_rsnxe(struct wpabuf *buf, u16 capab);
+
 #endif /* WPA_COMMON_H */
index 1f3dd08ba4c2e42a38bb393d867e5ddd198d77e9..736a6c7d6f96125a25ac89b907cd0d0b775c8d42 100644 (file)
@@ -619,6 +619,7 @@ static struct wpabuf * wpas_pasn_build_auth_1(struct wpa_supplicant *wpa_s)
        const u8 *pmkid;
        u8 wrapped_data;
        int ret;
+       u16 capab;
 
        wpa_printf(MSG_DEBUG, "PASN: Building frame 1");
 
@@ -684,6 +685,17 @@ static struct wpabuf * wpas_pasn_build_auth_1(struct wpa_supplicant *wpa_s)
        if (wpa_pasn_add_wrapped_data(buf, wrapped_data_buf) < 0)
                goto fail;
 
+       /* Add own RNSXE */
+       /* TODO: How to handle protected TWT and SAE H2E? */
+       capab = 0;
+       if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_LTF)
+               capab |= WLAN_RSNX_CAPAB_SECURE_LTF;
+       if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_RTT)
+               capab |= WLAN_RSNX_CAPAB_SECURE_RTT;
+       if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_PROT_RANGE_NEG)
+               capab |= WLAN_RSNX_CAPAB_PROT_RANGE_NEG;
+       wpa_pasn_add_rsnxe(buf, capab);
+
        ret = pasn_auth_frame_hash(pasn->akmp, pasn->cipher,
                                   wpabuf_head_u8(buf) + IEEE80211_HDRLEN,
                                   wpabuf_len(buf) - IEEE80211_HDRLEN,
@@ -806,8 +818,8 @@ static void wpas_pasn_reset(struct wpa_supplicant *wpa_s)
        forced_memzero(&pasn->ptk, sizeof(pasn->ptk));
        forced_memzero(&pasn->hash, sizeof(pasn->hash));
 
-       wpabuf_free(pasn->beacon_rsne);
-       pasn->beacon_rsne = NULL;
+       wpabuf_free(pasn->beacon_rsne_rsnxe);
+       pasn->beacon_rsne_rsnxe = NULL;
 
 #ifdef CONFIG_SAE
        sae_clear_data(&pasn->sae);
@@ -926,6 +938,7 @@ static int wpas_pasn_set_pmk(struct wpa_supplicant *wpa_s,
 static int wpas_pasn_start(struct wpa_supplicant *wpa_s, const u8 *bssid,
                           int akmp, int cipher, u16 group, int freq,
                           const u8 *beacon_rsne, u8 beacon_rsne_len,
+                          const u8 *beacon_rsnxe, u8 beacon_rsnxe_len,
                           int network_id)
 {
        struct wpas_pasn *pasn = &wpa_s->pasn;
@@ -980,12 +993,18 @@ static int wpas_pasn_start(struct wpa_supplicant *wpa_s, const u8 *bssid,
                goto fail;
        }
 
-       pasn->beacon_rsne = wpabuf_alloc_copy(beacon_rsne, beacon_rsne_len);
-       if (!pasn->beacon_rsne) {
-               wpa_printf(MSG_DEBUG, "PASN: Failed storing beacon RSNE");
+       pasn->beacon_rsne_rsnxe = wpabuf_alloc(beacon_rsne_len +
+                                              beacon_rsnxe_len);
+       if (!pasn->beacon_rsne_rsnxe) {
+               wpa_printf(MSG_DEBUG, "PASN: Failed storing beacon RSNE/RSNXE");
                goto fail;
        }
 
+       wpabuf_put_data(pasn->beacon_rsne_rsnxe, beacon_rsne, beacon_rsne_len);
+       if (beacon_rsnxe && beacon_rsnxe_len)
+               wpabuf_put_data(pasn->beacon_rsne_rsnxe, beacon_rsnxe,
+                               beacon_rsnxe_len);
+
        pasn->akmp = akmp;
        pasn->cipher = cipher;
        pasn->group = group;
@@ -1068,7 +1087,7 @@ static void wpas_pasn_auth_start_cb(struct wpa_radio_work *work, int deinit)
        struct wpa_supplicant *wpa_s = work->wpa_s;
        struct wpa_pasn_auth_work *awork = work->ctx;
        struct wpa_bss *bss;
-       const u8 *rsne;
+       const u8 *rsne, *rsnxe;
        int ret;
 
        wpa_printf(MSG_DEBUG, "PASN: auth_start_cb: deinit=%d", deinit);
@@ -1101,8 +1120,11 @@ static void wpas_pasn_auth_start_cb(struct wpa_radio_work *work, int deinit)
                goto fail;
        }
 
+       rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
+
        ret = wpas_pasn_start(wpa_s, awork->bssid, awork->akmp, awork->cipher,
                              awork->group, bss->freq, rsne, *(rsne + 1) + 2,
+                             rsnxe, rsnxe ? *(rsnxe + 1) + 2 : 0,
                              awork->network_id);
        if (ret) {
                wpa_printf(MSG_DEBUG,
@@ -1366,8 +1388,8 @@ int wpas_pasn_auth_rx(struct wpa_supplicant *wpa_s,
        /* Verify the MIC */
        ret = pasn_mic(pasn->ptk.kck, pasn->akmp, pasn->cipher,
                       pasn->bssid, wpa_s->own_addr,
-                      wpabuf_head(pasn->beacon_rsne),
-                      wpabuf_len(pasn->beacon_rsne),
+                      wpabuf_head(pasn->beacon_rsne_rsnxe),
+                      wpabuf_len(pasn->beacon_rsne_rsnxe),
                       (u8 *) &mgmt->u.auth,
                       len - offsetof(struct ieee80211_mgmt, u.auth),
                       out_mic);
index 2e8584565d2cf8bf39bf3b991877b654744a01f2..0ce7447fe72854c58648a6ebae5b8a1086ca50a8 100644 (file)
@@ -542,7 +542,7 @@ struct wpas_pasn {
 
        u8 hash[SHA384_MAC_LEN];
 
-       struct wpabuf *beacon_rsne;
+       struct wpabuf *beacon_rsne_rsnxe;
        struct wpa_ptk ptk;
        struct crypto_ecdh *ecdh;