}
-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;
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 */
{
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;
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);
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)
* 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;
* @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.
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 */
#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
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 */
const u8 *pmkid;
u8 wrapped_data;
int ret;
+ u16 capab;
wpa_printf(MSG_DEBUG, "PASN: Building frame 1");
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,
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);
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;
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;
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);
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,
/* 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);
u8 hash[SHA384_MAC_LEN];
- struct wpabuf *beacon_rsne;
+ struct wpabuf *beacon_rsne_rsnxe;
struct wpa_ptk ptk;
struct crypto_ecdh *ecdh;