PASN: Compute MIC from RSNE and RSNXE of the frame for Wi-Fi Aware

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>
This commit is contained in:
Vinay Gannevaram 2022-10-07 20:03:46 +05:30 committed by Jouni Malinen
parent 6f80014b10
commit 1711fe9121
2 changed files with 87 additions and 22 deletions

View 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;
rsn_ie = pasn->rsn_ie;
if (wpa_pasn_add_rsne(rsn_buf, pmkid,
pasn->akmp, pasn->cipher) < 0)
goto fail;
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;
}

View 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) {