From 1711fe9121c546e7be5e59c9db2715f0f3bbc6ae Mon Sep 17 00:00:00 2001 From: Vinay Gannevaram Date: Fri, 7 Oct 2022 20:03:46 +0530 Subject: [PATCH] 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 --- src/ap/ieee802_11.c | 25 ++++++++-- wpa_supplicant/pasn_supplicant.c | 84 ++++++++++++++++++++++++-------- 2 files changed, 87 insertions(+), 22 deletions(-) diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 810fc9ebd..5a87b30c4 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -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; } diff --git a/wpa_supplicant/pasn_supplicant.c b/wpa_supplicant/pasn_supplicant.c index 353e4ae9d..f7ada9dd3 100644 --- a/wpa_supplicant/pasn_supplicant.c +++ b/wpa_supplicant/pasn_supplicant.c @@ -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) {