WPA: Support deriving KDK based on capabilities

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>
This commit is contained in:
Ilan Peer 2020-12-16 13:01:39 +02:00 committed by Jouni Malinen
parent 9e7b980d65
commit dccb6cde03
5 changed files with 43 additions and 14 deletions

View 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;
}

View 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

View 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)) {

View 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;

View 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);