]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
PASN: Compute MIC from RSNE and RSNXE of the frame for Wi-Fi Aware
authorVinay Gannevaram <quic_vganneva@quicinc.com>
Fri, 7 Oct 2022 14:33:46 +0000 (20:03 +0530)
committerJouni Malinen <j@w1.fi>
Thu, 3 Nov 2022 22:52:17 +0000 (00:52 +0200)
Wi-Fi Aware R4 specification defines Beacon RSNE/RSNXE to be same as
RSNE/RSNXE present in Auth2 frame. So, MIC validation should be done
with the RSNE and RSNXE received in Auth2 frame.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
src/ap/ieee802_11.c
wpa_supplicant/pasn_supplicant.c

index 810fc9ebd41a45b22457d4c3c286162e7686434c..5a87b30c4cc285dfd7a81c91e7445e1581b29969 100644 (file)
@@ -3067,6 +3067,7 @@ static int handle_auth_pasn_resp(struct wpas_pasn *pasn, const u8 *own_addr,
                                 u16 status)
 {
        struct wpabuf *buf, *pubkey = NULL, *wrapped_data_buf = NULL;
+       struct wpabuf *rsn_buf = NULL;
        u8 mic[WPA_PASN_MAX_MIC_LEN];
        u8 mic_len;
        u8 *ptr;
@@ -3152,10 +3153,26 @@ static int handle_auth_pasn_resp(struct wpas_pasn *pasn, const u8 *own_addr,
        frame = wpabuf_head_u8(buf) + IEEE80211_HDRLEN;
        frame_len = wpabuf_len(buf) - IEEE80211_HDRLEN;
 
-       if (!pasn->rsn_ie || !pasn->rsn_ie_len)
-               goto fail;
+       if (pasn->rsn_ie && pasn->rsn_ie_len) {
+               rsn_ie = pasn->rsn_ie;
+       } else {
+               /*
+                * Note: when pasn->rsn_ie is NULL, it is likely that Beacon
+                * frame RSNE is not initialized. This is possible in case of
+                * PASN authentication used for Wi-Fi Aware for which Beacon
+                * frame RSNE and RSNXE are same as RSNE and RSNXE in the
+                * Authentication frame.
+                */
+               rsn_buf = wpabuf_alloc(500);
+               if (!rsn_buf)
+                       goto fail;
+
+               if (wpa_pasn_add_rsne(rsn_buf, pmkid,
+                                     pasn->akmp, pasn->cipher) < 0)
+                       goto fail;
 
-       rsn_ie = pasn->rsn_ie;
+               rsn_ie = wpabuf_head_u8(rsn_buf);
+       }
 
        /*
         * Note: wpa_auth_get_wpa_ie() might return not only the RSNE but also
@@ -3204,11 +3221,13 @@ done:
        if (ret)
                wpa_printf(MSG_INFO, "send_auth_reply: Send failed");
 
+       wpabuf_free(rsn_buf);
        wpabuf_free(buf);
        return ret;
 fail:
        wpabuf_free(wrapped_data_buf);
        wpabuf_free(pubkey);
+       wpabuf_free(rsn_buf);
        wpabuf_free(buf);
        return -1;
 }
index 353e4ae9dc99eef75a3c6e769690a074426007a8..f7ada9dd38911f9174a1f80ab575f034f0694e04 100644 (file)
@@ -1300,7 +1300,8 @@ static int wpas_pasn_start(struct wpas_pasn *pasn, const u8 *own_addr,
 #ifdef CONFIG_SAE
        case WPA_KEY_MGMT_SAE:
 
-               if (!ieee802_11_rsnx_capab(beacon_rsnxe,
+               if (beacon_rsnxe &&
+                   !ieee802_11_rsnx_capab(beacon_rsnxe,
                                           WLAN_RSNX_CAPAB_SAE_H2E)) {
                        wpa_printf(MSG_DEBUG,
                                   "PASN: AP does not support SAE H2E");
@@ -1333,17 +1334,21 @@ static int wpas_pasn_start(struct wpas_pasn *pasn, const u8 *own_addr,
                goto fail;
        }
 
-       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;
-       }
+       if (beacon_rsne && beacon_rsne_len) {
+               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);
+               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;
@@ -1920,14 +1925,55 @@ static int wpa_pasn_auth_rx(struct wpas_pasn *pasn, const u8 *data, size_t len,
        wpabuf_free(secret);
        secret = NULL;
 
-       /* Verify the MIC */
-       ret = pasn_mic(pasn->ptk.kck, pasn->akmp, pasn->cipher,
-                      pasn->bssid, pasn->own_addr,
-                      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);
+       if (pasn->beacon_rsne_rsnxe) {
+               /* Verify the MIC */
+               ret = pasn_mic(pasn->ptk.kck, pasn->akmp, pasn->cipher,
+                              pasn->bssid, pasn->own_addr,
+                              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);
+       } else {
+               u8 *rsne_rsnxe;
+               size_t rsne_rsnxe_len = 0;
+
+               /*
+                * Note: When Beacon rsne_rsnxe is not initialized, it is likely
+                * that this is for Wi-Fi Aware using PASN handshake for which
+                * Beacon RSNE/RSNXE are same as RSNE/RSNXE in the
+                * Authentication frame
+                */
+               if (elems.rsn_ie && elems.rsn_ie_len)
+                       rsne_rsnxe_len += elems.rsn_ie_len + 2;
+               if (elems.rsnxe && elems.rsnxe_len)
+                       rsne_rsnxe_len += elems.rsnxe_len + 2;
+
+               rsne_rsnxe = os_zalloc(rsne_rsnxe_len);
+               if (!rsne_rsnxe)
+                       goto fail;
+
+               if (elems.rsn_ie && elems.rsn_ie_len)
+                       os_memcpy(rsne_rsnxe, elems.rsn_ie - 2,
+                                 elems.rsn_ie_len + 2);
+               if (elems.rsnxe && elems.rsnxe_len)
+                       os_memcpy(rsne_rsnxe + elems.rsn_ie_len + 2,
+                                 elems.rsnxe - 2, elems.rsnxe_len + 2);
+
+               wpa_hexdump_key(MSG_DEBUG, "PASN: RSN + RSNXE buf",
+                               rsne_rsnxe, rsne_rsnxe_len);
+
+               /* Verify the MIC */
+               ret = pasn_mic(pasn->ptk.kck, pasn->akmp, pasn->cipher,
+                              pasn->bssid, pasn->own_addr,
+                              rsne_rsnxe,
+                              rsne_rsnxe_len,
+                              (u8 *) &mgmt->u.auth,
+                              len - offsetof(struct ieee80211_mgmt, u.auth),
+                              out_mic);
+
+               os_free(rsne_rsnxe);
+       }
 
        wpa_hexdump_key(MSG_DEBUG, "PASN: Frame MIC", mic, mic_len);
        if (ret || os_memcmp(mic, out_mic, mic_len) != 0) {