From 8c786e068772b79eadef61129a574fb0edd5107c Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Thu, 8 Apr 2021 12:06:20 +0300 Subject: [PATCH] PASN: Derive KDK only when required When a PTK derivation is done as part of PASN authentication flow, a KDK derivation should be done if and only if the higher layer protocol is supported by both parties. Fix the code accordingly, so KDK would be derived if and only if both sides support Secure LTF. Signed-off-by: Ilan Peer --- src/ap/ieee802_11.c | 13 +++++++++++-- src/ap/sta_info.h | 1 + wpa_supplicant/pasn_supplicant.c | 13 ++++++++++++- wpa_supplicant/wpa_supplicant_i.h | 1 + 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 877d03e3a..1b0384dfc 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -2646,7 +2646,7 @@ static void pasn_fils_auth_resp(struct hostapd_data *hapd, wpabuf_head(pasn->secret), wpabuf_len(pasn->secret), &sta->pasn->ptk, sta->pasn->akmp, - sta->pasn->cipher, WPA_KDK_MAX_LEN); + sta->pasn->cipher, sta->pasn->kdk_len); if (ret) { wpa_printf(MSG_DEBUG, "PASN: FILS: Failed to derive PTK"); goto fail; @@ -2883,7 +2883,7 @@ pasn_derive_keys(struct hostapd_data *hapd, struct sta_info *sta, ret = pasn_pmk_to_ptk(pmk, pmk_len, sta->addr, hapd->own_addr, wpabuf_head(secret), wpabuf_len(secret), &sta->pasn->ptk, sta->pasn->akmp, - sta->pasn->cipher, WPA_KDK_MAX_LEN); + sta->pasn->cipher, sta->pasn->kdk_len); if (ret) { wpa_printf(MSG_DEBUG, "PASN: Failed to derive PTK"); return -1; @@ -3151,6 +3151,15 @@ static void handle_auth_pasn_1(struct hostapd_data *hapd, struct sta_info *sta, sta->pasn->akmp = rsn_data.key_mgmt; sta->pasn->cipher = rsn_data.pairwise_cipher; + if (hapd->conf->force_kdk_derivation || + ((hapd->iface->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_LTF) && + elems.rsnxe && elems.rsnxe_len >= 2 && + (WPA_GET_LE16(elems.rsnxe) & BIT(WLAN_RSNX_CAPAB_SECURE_LTF)))) + sta->pasn->kdk_len = WPA_KDK_MAX_LEN; + else + sta->pasn->kdk_len = 0; + wpa_printf(MSG_DEBUG, "PASN: kdk_len=%zu", sta->pasn->kdk_len); + if (!elems.pasn_params || !elems.pasn_params_len) { wpa_printf(MSG_DEBUG, "PASN: No PASN Parameters element found"); diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h index efa48e7e3..27e72f9a0 100644 --- a/src/ap/sta_info.h +++ b/src/ap/sta_info.h @@ -88,6 +88,7 @@ struct pasn_data { u16 group; u8 trans_seq; u8 wrapped_data_format; + size_t kdk_len; u8 hash[SHA384_MAC_LEN]; struct wpa_ptk ptk; diff --git a/wpa_supplicant/pasn_supplicant.c b/wpa_supplicant/pasn_supplicant.c index 53ba21c5a..d483175b7 100644 --- a/wpa_supplicant/pasn_supplicant.c +++ b/wpa_supplicant/pasn_supplicant.c @@ -1052,6 +1052,17 @@ static int wpas_pasn_start(struct wpa_supplicant *wpa_s, const u8 *bssid, pasn->cipher = cipher; pasn->group = group; pasn->freq = freq; + + if (wpa_s->conf->force_kdk_derivation || + (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_LTF && + beacon_rsnxe && beacon_rsnxe_len >= 4 && + (WPA_GET_LE16(beacon_rsnxe + 2) & + BIT(WLAN_RSNX_CAPAB_SECURE_LTF)))) + pasn->kdk_len = WPA_KDK_MAX_LEN; + else + pasn->kdk_len = 0; + wpa_printf(MSG_DEBUG, "PASN: kdk_len=%zu", pasn->kdk_len); + os_memcpy(pasn->bssid, bssid, ETH_ALEN); wpa_printf(MSG_DEBUG, @@ -1480,7 +1491,7 @@ int wpas_pasn_auth_rx(struct wpa_supplicant *wpa_s, wpa_s->own_addr, pasn->bssid, wpabuf_head(secret), wpabuf_len(secret), &pasn->ptk, pasn->akmp, pasn->cipher, - WPA_KDK_MAX_LEN); + pasn->kdk_len); if (ret) { wpa_printf(MSG_DEBUG, "PASN: Failed to derive PTK"); goto fail; diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 8813ddb71..49007cfc2 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -539,6 +539,7 @@ struct wpas_pasn { int cipher; u16 group; int freq; + size_t kdk_len; u8 trans_seq; u8 status;