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 <ilan.peer@intel.com>
This commit is contained in:
Ilan Peer 2021-04-08 12:06:20 +03:00 committed by Jouni Malinen
parent 655edc19cf
commit 8c786e0687
4 changed files with 25 additions and 3 deletions

View file

@ -2646,7 +2646,7 @@ static void pasn_fils_auth_resp(struct hostapd_data *hapd,
wpabuf_head(pasn->secret), wpabuf_head(pasn->secret),
wpabuf_len(pasn->secret), wpabuf_len(pasn->secret),
&sta->pasn->ptk, sta->pasn->akmp, &sta->pasn->ptk, sta->pasn->akmp,
sta->pasn->cipher, WPA_KDK_MAX_LEN); sta->pasn->cipher, sta->pasn->kdk_len);
if (ret) { if (ret) {
wpa_printf(MSG_DEBUG, "PASN: FILS: Failed to derive PTK"); wpa_printf(MSG_DEBUG, "PASN: FILS: Failed to derive PTK");
goto fail; 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, ret = pasn_pmk_to_ptk(pmk, pmk_len, sta->addr, hapd->own_addr,
wpabuf_head(secret), wpabuf_len(secret), wpabuf_head(secret), wpabuf_len(secret),
&sta->pasn->ptk, sta->pasn->akmp, &sta->pasn->ptk, sta->pasn->akmp,
sta->pasn->cipher, WPA_KDK_MAX_LEN); sta->pasn->cipher, sta->pasn->kdk_len);
if (ret) { if (ret) {
wpa_printf(MSG_DEBUG, "PASN: Failed to derive PTK"); wpa_printf(MSG_DEBUG, "PASN: Failed to derive PTK");
return -1; 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->akmp = rsn_data.key_mgmt;
sta->pasn->cipher = rsn_data.pairwise_cipher; 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) { if (!elems.pasn_params || !elems.pasn_params_len) {
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
"PASN: No PASN Parameters element found"); "PASN: No PASN Parameters element found");

View file

@ -88,6 +88,7 @@ struct pasn_data {
u16 group; u16 group;
u8 trans_seq; u8 trans_seq;
u8 wrapped_data_format; u8 wrapped_data_format;
size_t kdk_len;
u8 hash[SHA384_MAC_LEN]; u8 hash[SHA384_MAC_LEN];
struct wpa_ptk ptk; struct wpa_ptk ptk;

View file

@ -1052,6 +1052,17 @@ static int wpas_pasn_start(struct wpa_supplicant *wpa_s, const u8 *bssid,
pasn->cipher = cipher; pasn->cipher = cipher;
pasn->group = group; pasn->group = group;
pasn->freq = freq; 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); os_memcpy(pasn->bssid, bssid, ETH_ALEN);
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
@ -1480,7 +1491,7 @@ int wpas_pasn_auth_rx(struct wpa_supplicant *wpa_s,
wpa_s->own_addr, pasn->bssid, wpa_s->own_addr, pasn->bssid,
wpabuf_head(secret), wpabuf_len(secret), wpabuf_head(secret), wpabuf_len(secret),
&pasn->ptk, pasn->akmp, pasn->cipher, &pasn->ptk, pasn->akmp, pasn->cipher,
WPA_KDK_MAX_LEN); pasn->kdk_len);
if (ret) { if (ret) {
wpa_printf(MSG_DEBUG, "PASN: Failed to derive PTK"); wpa_printf(MSG_DEBUG, "PASN: Failed to derive PTK");
goto fail; goto fail;

View file

@ -539,6 +539,7 @@ struct wpas_pasn {
int cipher; int cipher;
u16 group; u16 group;
int freq; int freq;
size_t kdk_len;
u8 trans_seq; u8 trans_seq;
u8 status; u8 status;