]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
WPA: Support deriving KDK based on capabilities
authorIlan Peer <ilan.peer@intel.com>
Wed, 16 Dec 2020 11:01:39 +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 station and the AP declare
support for secure LTF.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
src/rsn_supp/wpa.c
src/rsn_supp/wpa.h
src/rsn_supp/wpa_ft.c
src/rsn_supp/wpa_i.h
wpa_supplicant/wpas_glue.c

index 9ef07311403e03efcb7441ee047f0f73b4c32d36..e1aba36de93d41c68523dd4b0084160f325f66bb 100644 (file)
@@ -579,7 +579,7 @@ static int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr,
                          const struct wpa_eapol_key *key, struct wpa_ptk *ptk)
 {
        const u8 *z = NULL;
-       size_t z_len = 0;
+       size_t z_len = 0, kdk_len;
        int akmp;
 
 #ifdef CONFIG_IEEE80211R
@@ -603,11 +603,19 @@ static int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr,
                akmp |= WPA_KEY_MGMT_PSK_SHA256;
        }
 #endif /* CONFIG_OWE */
+
+       if (sm->force_kdk_derivation ||
+           (sm->secure_ltf && sm->ap_rsnxe && sm->ap_rsnxe_len >= 4 &&
+            sm->ap_rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8)))
+               kdk_len = WPA_KDK_MAX_LEN;
+       else
+               kdk_len = 0;
+
        return wpa_pmk_to_ptk(sm->pmk, sm->pmk_len, "Pairwise key expansion",
                              sm->own_addr, sm->bssid, sm->snonce,
                              key->key_nonce, ptk, akmp,
                              sm->pairwise_cipher, z, z_len,
-                             sm->kdk ? WPA_KDK_MAX_LEN : 0);
+                             kdk_len);
 }
 
 
@@ -3188,7 +3196,7 @@ void wpa_sm_set_config(struct wpa_sm *sm, struct rsn_supp_config *config)
                sm->p2p = config->p2p;
                sm->wpa_rsc_relaxation = config->wpa_rsc_relaxation;
                sm->owe_ptk_workaround = config->owe_ptk_workaround;
-               sm->kdk = config->kdk;
+               sm->force_kdk_derivation = config->force_kdk_derivation;
 #ifdef CONFIG_FILS
                if (config->fils_cache_id) {
                        sm->fils_cache_id_set = 1;
@@ -3211,7 +3219,7 @@ void wpa_sm_set_config(struct wpa_sm *sm, struct rsn_supp_config *config)
                sm->wpa_rsc_relaxation = 0;
                sm->owe_ptk_workaround = 0;
                sm->beacon_prot = 0;
-               sm->kdk = false;
+               sm->force_kdk_derivation = false;
        }
 }
 
@@ -4134,7 +4142,7 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data,
        const u8 *g_sta = NULL;
        size_t g_sta_len = 0;
        const u8 *g_ap = NULL;
-       size_t g_ap_len = 0;
+       size_t g_ap_len = 0, kdk_len;
        struct wpabuf *pub = NULL;
 
        os_memcpy(sm->bssid, bssid, ETH_ALEN);
@@ -4362,6 +4370,13 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data,
                goto fail;
        }
 
+       if (sm->force_kdk_derivation ||
+           (sm->secure_ltf && sm->ap_rsnxe && sm->ap_rsnxe_len >= 4 &&
+            sm->ap_rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8)))
+               kdk_len = WPA_KDK_MAX_LEN;
+       else
+               kdk_len = 0;
+
        if (fils_pmk_to_ptk(sm->pmk, sm->pmk_len, sm->own_addr, sm->bssid,
                            sm->fils_nonce, sm->fils_anonce,
                            dh_ss ? wpabuf_head(dh_ss) : NULL,
@@ -4369,7 +4384,7 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data,
                            &sm->ptk, ick, &ick_len,
                            sm->key_mgmt, sm->pairwise_cipher,
                            sm->fils_ft, &sm->fils_ft_len,
-                           sm->kdk ? WPA_KDK_MAX_LEN : 0) < 0) {
+                           kdk_len) < 0) {
                wpa_printf(MSG_DEBUG, "FILS: Failed to derive PTK");
                goto fail;
        }
index 9f0861cd2d89105b37f97b1a2a074bcfd9b7c3e6..8e4533e4568293d54749ee86362041acfd666992 100644 (file)
@@ -132,7 +132,7 @@ struct rsn_supp_config {
        int owe_ptk_workaround;
        const u8 *fils_cache_id;
        int beacon_prot;
-       bool kdk;
+       bool force_kdk_derivation;
 };
 
 #ifndef CONFIG_NO_WPA
index 28985f23884cdca522da593546c6cd2c30e6e20e..c26f1a5cd291b82e7ec783799d5a3e6572db6194 100644 (file)
@@ -40,7 +40,7 @@ int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr,
        const u8 *anonce = key->key_nonce;
        int use_sha384 = wpa_key_mgmt_sha384(sm->key_mgmt);
        const u8 *mpmk;
-       size_t mpmk_len;
+       size_t mpmk_len, kdk_len;
 
        if (sm->xxkey_len > 0) {
                mpmk = sm->xxkey;
@@ -68,10 +68,17 @@ int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr,
 
        wpa_ft_pasn_store_r1kh(sm, src_addr);
 
+       if (sm->force_kdk_derivation ||
+           (sm->secure_ltf && sm->ap_rsnxe && sm->ap_rsnxe_len >= 4 &&
+            sm->ap_rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8)))
+               kdk_len = WPA_KDK_MAX_LEN;
+       else
+               kdk_len = 0;
+
        return wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->pmk_r1_len, sm->snonce, anonce,
                                 sm->own_addr, sm->bssid, sm->pmk_r1_name, ptk,
                                 ptk_name, sm->key_mgmt, sm->pairwise_cipher,
-                                sm->kdk ? WPA_KDK_MAX_LEN : 0);
+                                kdk_len);
 }
 
 
@@ -539,7 +546,7 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
        int ret;
        const u8 *bssid;
        const u8 *kck;
-       size_t kck_len;
+       size_t kck_len, kdk_len;
        int use_sha384 = wpa_key_mgmt_sha384(sm->key_mgmt);
        const u8 *anonce, *snonce;
 
@@ -664,11 +671,18 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
 
        wpa_ft_pasn_store_r1kh(sm, bssid);
 
+       if (sm->force_kdk_derivation ||
+           (sm->secure_ltf && sm->ap_rsnxe && sm->ap_rsnxe_len >= 4 &&
+            sm->ap_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(sm->pmk_r1, sm->pmk_r1_len, sm->snonce,
                              anonce, sm->own_addr, bssid,
                              sm->pmk_r1_name, &sm->ptk, ptk_name, sm->key_mgmt,
                              sm->pairwise_cipher,
-                             sm->kdk ? WPA_KDK_MAX_LEN : 0) < 0)
+                             kdk_len) < 0)
                return -1;
 
        if (wpa_key_mgmt_fils(sm->key_mgmt)) {
index 16f089c48bc20a136556d7c8576fea30f7198d22..1dc9639634bfe057a7a8ce26d65fca75ae3b4b1f 100644 (file)
@@ -80,9 +80,9 @@ struct wpa_sm {
 
        /*
         * 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;
 
        u8 own_addr[ETH_ALEN];
        const char *ifname;
index b914d2974b4340eec1888b8c8ec1ef5e9e27ab10..798b5b461e7a722d2a2e973a6918d68dcde387bf 100644 (file)
@@ -1477,7 +1477,7 @@ void wpa_supplicant_rsn_supp_set_config(struct wpa_supplicant *wpa_s,
        }
 #ifdef CONFIG_PASN
 #ifdef CONFIG_TESTING_OPTIONS
-       conf.kdk = wpa_s->conf->force_kdk_derivation;
+       conf.force_kdk_derivation = wpa_s->conf->force_kdk_derivation;
 #endif /* CONFIG_TESTING_OPTIONS */
 #endif /* CONFIG_PASN*/
        wpa_sm_set_config(wpa_s->wpa, ssid ? &conf : NULL);