]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
WPA: Support deriving KDK based on capabilities (Authenticator)
authorIlan Peer <ilan.peer@intel.com>
Wed, 16 Dec 2020 11:01:40 +0000 (13:01 +0200)
committerJouni Malinen <j@w1.fi>
Tue, 26 Jan 2021 21:09:39 +0000 (23:09 +0200)
Derive the KDK as part of PMK to PTK derivation if forced by
configuration or in case both the local AP and the peer station declare
support for secure LTF.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
src/ap/wpa_auth.c
src/ap/wpa_auth.h
src/ap/wpa_auth_ft.c
src/ap/wpa_auth_glue.c

index e6dfb34d11c468100c110696bb5ad277d0089b4f..acb4416c5fb1f4d9c6aa26a3157b44c924f18553 100644 (file)
@@ -2278,9 +2278,17 @@ static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
                          struct wpa_ptk *ptk, int force_sha256)
 {
        const u8 *z = NULL;
-       size_t z_len = 0;
+       size_t z_len = 0, kdk_len;
        int akmp;
 
+       if (sm->wpa_auth->conf.force_kdk_derivation ||
+           (sm->wpa_auth->conf.secure_ltf &&
+            sm->rsnxe && sm->rsnxe_len >= 4 &&
+            sm->rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8)))
+               kdk_len = WPA_KDK_MAX_LEN;
+       else
+               kdk_len = 0;
+
 #ifdef CONFIG_IEEE80211R_AP
        if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
                if (sm->ft_completed) {
@@ -2293,8 +2301,7 @@ static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
                                                 ptk, ptk_name,
                                                 sm->wpa_key_mgmt,
                                                 sm->pairwise,
-                                                sm->wpa_auth->conf.kdk ?
-                                                WPA_KDK_MAX_LEN : 0);
+                                                kdk_len);
                }
                return wpa_auth_derive_ptk_ft(sm, ptk);
        }
@@ -2312,8 +2319,7 @@ static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
                akmp |= WPA_KEY_MGMT_PSK_SHA256;
        return wpa_pmk_to_ptk(pmk, pmk_len, "Pairwise key expansion",
                              sm->wpa_auth->addr, sm->addr, sm->ANonce, snonce,
-                             ptk, akmp, sm->pairwise, z, z_len,
-                             sm->wpa_auth->conf.kdk ? WPA_KDK_MAX_LEN : 0);
+                             ptk, akmp, sm->pairwise, z, z_len, kdk_len);
 }
 
 
@@ -2328,14 +2334,21 @@ int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk,
        size_t ick_len;
        int res;
        u8 fils_ft[FILS_FT_MAX_LEN];
-       size_t fils_ft_len = 0;
+       size_t fils_ft_len = 0, kdk_len;
+
+       if (sm->wpa_auth->conf.force_kdk_derivation ||
+           (sm->wpa_auth->conf.secure_ltf &&
+            sm->rsnxe && sm->rsnxe_len >= 4 &&
+            sm->rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8)))
+               kdk_len = WPA_KDK_MAX_LEN;
+       else
+               kdk_len = 0;
 
        res = fils_pmk_to_ptk(pmk, pmk_len, sm->addr, sm->wpa_auth->addr,
                              snonce, anonce, dhss, dhss_len,
                              &sm->PTK, ick, &ick_len,
                              sm->wpa_key_mgmt, sm->pairwise,
-                             fils_ft, &fils_ft_len,
-                             sm->wpa_auth->conf.kdk ? WPA_KDK_MAX_LEN : 0);
+                             fils_ft, &fils_ft_len, kdk_len);
        if (res < 0)
                return res;
        sm->PTK_valid = true;
index 0a16141edf99832c95e5620189847032d1d01de9..cf0801dc3e660000234c77bb1747ff69390d5d28 100644 (file)
@@ -270,9 +270,9 @@ struct wpa_auth_config {
 
        /*
         * If set Key Derivation Key should be derived as part of PMK to
-        * PTK derivation.
+        * PTK derivation regardless of advertised capabilities.
         */
-       bool kdk;
+       bool force_kdk_derivation;
 };
 
 typedef enum {
index 115a6fa2f3ba05d2d4816fc94426c1b6e653e252..32b745651ace85d86f0ebda77824cd1abfd472f0 100644 (file)
@@ -3066,7 +3066,7 @@ static int wpa_ft_process_auth_req(struct wpa_state_machine *sm,
        const u8 *identity, *radius_cui;
        size_t identity_len = 0, radius_cui_len = 0;
        int use_sha384;
-       size_t pmk_r1_len;
+       size_t pmk_r1_len, kdk_len;
 
        *resp_ies = NULL;
        *resp_ies_len = 0;
@@ -3196,12 +3196,18 @@ pmk_r1_derived:
        wpa_hexdump(MSG_DEBUG, "FT: Generated ANonce",
                    sm->ANonce, WPA_NONCE_LEN);
 
+       if (sm->wpa_auth->conf.force_kdk_derivation ||
+           (sm->wpa_auth->conf.secure_ltf &&
+            sm->rsnxe && sm->rsnxe_len >= 4 &&
+            sm->rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8)))
+               kdk_len = WPA_KDK_MAX_LEN;
+       else
+               kdk_len = 0;
+
        if (wpa_pmk_r1_to_ptk(pmk_r1, pmk_r1_len, sm->SNonce, sm->ANonce,
                              sm->addr, sm->wpa_auth->addr, pmk_r1_name,
                              &sm->PTK, ptk_name, sm->wpa_key_mgmt,
-                             pairwise,
-                             sm->wpa_auth->conf.kdk ?
-                             WPA_KDK_MAX_LEN : 0) < 0)
+                             pairwise, kdk_len) < 0)
                return WLAN_STATUS_UNSPECIFIED_FAILURE;
 
        sm->pairwise = pairwise;
index 23025b36ab4a436cd1d9fff2e9aae8d9a08e9e8b..ebc35dd296ffc6299b3aa6a0a19ff5a8f92c0d05 100644 (file)
@@ -211,7 +211,7 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
 #endif /* CONFIG_DPP2 */
 #ifdef CONFIG_PASN
 #ifdef CONFIG_TESTING_OPTIONS
-       wconf->kdk = conf->force_kdk_derivation;
+       wconf->force_kdk_derivation = conf->force_kdk_derivation;
 #endif /* CONFIG_TESTING_OPTIONS */
 #endif /* CONFIG_PASN */
 }