FT: Store PMK-R0/PMK-R1 after EAPOL-Key msg 2/4 MIC validation

hostapd was previously storing the derived PMK-R0 and PMK-R1 as soon as
these keys were derived. While that is fine for most purposes, it is
unnecessary to do that so quickly and if anything were to fail before
the supplicant is able to return a valid EAPOL-Key msg 2/4, there would
not really be any real use for the derived keys.

For the special case of FT-PSK and VLAN determination based on the
wpa_psk file, the VLAN information is set in the per-STA data structures
only after the EAPOL-Key msg 2/4 MIC has been verified. This ended up
storing the PMK-R0/PMK-R1 entries without correct VLAN assignment and as
such, any use of the FT protocol would not be able to transfer the VLAN
information through RRB.

Split local storing of the FT key hierarchy for the cases using the FT
4-way handshake so that PMK-R0 and PMK-R1 are first derived and then
stored as a separate step after having verified the MIC in the EAPOL-Key
msg 2/4 (i.e., after having confirmed the per-STA passphrase/PSK was
selected) and VLAN update. This fixes VLAN information for the
wpa_psk_file cases with FT-PSK.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
This commit is contained in:
Jouni Malinen 2023-02-14 11:29:30 +02:00 committed by Jouni Malinen
parent e4d1000cac
commit ba150059d1
3 changed files with 107 additions and 58 deletions

View file

@ -59,7 +59,9 @@ static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth,
struct wpa_group *group); struct wpa_group *group);
static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce, static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
const u8 *pmk, unsigned int pmk_len, const u8 *pmk, unsigned int pmk_len,
struct wpa_ptk *ptk, int force_sha256); struct wpa_ptk *ptk, int force_sha256,
u8 *pmk_r0, u8 *pmk_r1, u8 *pmk_r0_name,
size_t *key_len);
static void wpa_group_free(struct wpa_authenticator *wpa_auth, static void wpa_group_free(struct wpa_authenticator *wpa_auth,
struct wpa_group *group); struct wpa_group *group);
static void wpa_group_get(struct wpa_authenticator *wpa_auth, static void wpa_group_get(struct wpa_authenticator *wpa_auth,
@ -950,6 +952,10 @@ static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data,
const u8 *pmk = NULL; const u8 *pmk = NULL;
size_t pmk_len; size_t pmk_len;
int vlan_id = 0; int vlan_id = 0;
u8 pmk_r0[PMK_LEN_MAX], pmk_r0_name[WPA_PMK_NAME_LEN];
u8 pmk_r1[PMK_LEN_MAX];
size_t key_len;
int ret = -1;
os_memset(&PTK, 0, sizeof(PTK)); os_memset(&PTK, 0, sizeof(PTK));
for (;;) { for (;;) {
@ -971,8 +977,8 @@ static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data,
pmk_len = sm->pmk_len; pmk_len = sm->pmk_len;
} }
if (wpa_derive_ptk(sm, sm->alt_SNonce, pmk, pmk_len, &PTK, 0) < if (wpa_derive_ptk(sm, sm->alt_SNonce, pmk, pmk_len, &PTK, 0,
0) pmk_r0, pmk_r1, pmk_r0_name, &key_len) < 0)
break; break;
if (wpa_verify_key_mic(sm->wpa_key_mgmt, pmk_len, &PTK, if (wpa_verify_key_mic(sm->wpa_key_mgmt, pmk_len, &PTK,
@ -993,7 +999,7 @@ static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data,
if (!ok) { if (!ok) {
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
"WPA: Earlier SNonce did not result in matching MIC"); "WPA: Earlier SNonce did not result in matching MIC");
return -1; goto fail;
} }
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
@ -1002,14 +1008,26 @@ static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data,
if (vlan_id && wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) && if (vlan_id && wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
wpa_auth_update_vlan(sm->wpa_auth, sm->addr, vlan_id) < 0) wpa_auth_update_vlan(sm->wpa_auth, sm->addr, vlan_id) < 0)
return -1; goto fail;
#ifdef CONFIG_IEEE80211R_AP
if (wpa_key_mgmt_ft(sm->wpa_key_mgmt) && !sm->ft_completed) {
wpa_printf(MSG_DEBUG, "FT: Store PMK-R0/PMK-R1");
wpa_auth_ft_store_keys(sm, pmk_r0, pmk_r1, pmk_r0_name,
key_len);
}
#endif /* CONFIG_IEEE80211R_AP */
os_memcpy(sm->SNonce, sm->alt_SNonce, WPA_NONCE_LEN); os_memcpy(sm->SNonce, sm->alt_SNonce, WPA_NONCE_LEN);
os_memcpy(&sm->PTK, &PTK, sizeof(PTK)); os_memcpy(&sm->PTK, &PTK, sizeof(PTK));
forced_memzero(&PTK, sizeof(PTK)); forced_memzero(&PTK, sizeof(PTK));
sm->PTK_valid = true; sm->PTK_valid = true;
return 0; ret = 0;
fail:
forced_memzero(pmk_r0, sizeof(pmk_r0));
forced_memzero(pmk_r1, sizeof(pmk_r1));
return ret;
} }
@ -2347,7 +2365,9 @@ SM_STATE(WPA_PTK, PTKSTART)
static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce, static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
const u8 *pmk, unsigned int pmk_len, const u8 *pmk, unsigned int pmk_len,
struct wpa_ptk *ptk, int force_sha256) struct wpa_ptk *ptk, int force_sha256,
u8 *pmk_r0, u8 *pmk_r1, u8 *pmk_r0_name,
size_t *key_len)
{ {
const u8 *z = NULL; const u8 *z = NULL;
size_t z_len = 0, kdk_len; size_t z_len = 0, kdk_len;
@ -2373,7 +2393,8 @@ static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
ptk_name, sm->wpa_key_mgmt, ptk_name, sm->wpa_key_mgmt,
sm->pairwise, kdk_len); sm->pairwise, kdk_len);
} else { } else {
ret = wpa_auth_derive_ptk_ft(sm, ptk); ret = wpa_auth_derive_ptk_ft(sm, ptk, pmk_r0, pmk_r1,
pmk_r0_name, key_len);
} }
if (ret) { if (ret) {
wpa_printf(MSG_ERROR, "FT: PTK derivation failed"); wpa_printf(MSG_ERROR, "FT: PTK derivation failed");
@ -3058,6 +3079,9 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
struct wpa_eapol_ie_parse kde; struct wpa_eapol_ie_parse kde;
int vlan_id = 0; int vlan_id = 0;
int owe_ptk_workaround = !!wpa_auth->conf.owe_ptk_workaround; int owe_ptk_workaround = !!wpa_auth->conf.owe_ptk_workaround;
u8 pmk_r0[PMK_LEN_MAX], pmk_r0_name[WPA_PMK_NAME_LEN];
u8 pmk_r1[PMK_LEN_MAX];
size_t key_len;
SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING, wpa_ptk); SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING, wpa_ptk);
sm->EAPOLKeyReceived = false; sm->EAPOLKeyReceived = false;
@ -3096,7 +3120,8 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
} }
if (wpa_derive_ptk(sm, sm->SNonce, pmk, pmk_len, &PTK, if (wpa_derive_ptk(sm, sm->SNonce, pmk, pmk_len, &PTK,
owe_ptk_workaround == 2) < 0) owe_ptk_workaround == 2, pmk_r0, pmk_r1,
pmk_r0_name, &key_len) < 0)
break; break;
if (mic_len && if (mic_len &&
@ -3145,7 +3170,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
sm->last_rx_eapol_key, sm->last_rx_eapol_key,
sm->last_rx_eapol_key_len); sm->last_rx_eapol_key_len);
sm->waiting_radius_psk = 1; sm->waiting_radius_psk = 1;
return; goto out;
} }
if (!ok) { if (!ok) {
@ -3153,7 +3178,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
"invalid MIC in msg 2/4 of 4-Way Handshake"); "invalid MIC in msg 2/4 of 4-Way Handshake");
if (psk_found) if (psk_found)
wpa_auth_psk_failure_report(sm->wpa_auth, sm->addr); wpa_auth_psk_failure_report(sm->wpa_auth, sm->addr);
return; goto out;
} }
/* /*
@ -3167,12 +3192,12 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
key_data_length = WPA_GET_BE16(mic + mic_len); key_data_length = WPA_GET_BE16(mic + mic_len);
if (key_data_length > sm->last_rx_eapol_key_len - sizeof(*hdr) - if (key_data_length > sm->last_rx_eapol_key_len - sizeof(*hdr) -
sizeof(*key) - mic_len - 2) sizeof(*key) - mic_len - 2)
return; goto out;
if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) { if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) {
wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
"received EAPOL-Key msg 2/4 with invalid Key Data contents"); "received EAPOL-Key msg 2/4 with invalid Key Data contents");
return; goto out;
} }
if (kde.rsn_ie) { if (kde.rsn_ie) {
eapol_key_ie = kde.rsn_ie; eapol_key_ie = kde.rsn_ie;
@ -3199,7 +3224,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
/* MLME-DEAUTHENTICATE.request */ /* MLME-DEAUTHENTICATE.request */
wpa_sta_disconnect(wpa_auth, sm->addr, wpa_sta_disconnect(wpa_auth, sm->addr,
WLAN_REASON_PREV_AUTH_NOT_VALID); WLAN_REASON_PREV_AUTH_NOT_VALID);
return; goto out;
} }
if ((!sm->rsnxe && kde.rsnxe) || if ((!sm->rsnxe && kde.rsnxe) ||
(sm->rsnxe && !kde.rsnxe) || (sm->rsnxe && !kde.rsnxe) ||
@ -3215,7 +3240,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
/* MLME-DEAUTHENTICATE.request */ /* MLME-DEAUTHENTICATE.request */
wpa_sta_disconnect(wpa_auth, sm->addr, wpa_sta_disconnect(wpa_auth, sm->addr,
WLAN_REASON_PREV_AUTH_NOT_VALID); WLAN_REASON_PREV_AUTH_NOT_VALID);
return; goto out;
} }
#ifdef CONFIG_OCV #ifdef CONFIG_OCV
if (wpa_auth_uses_ocv(sm)) { if (wpa_auth_uses_ocv(sm)) {
@ -3227,14 +3252,14 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
if (wpa_channel_info(wpa_auth, &ci) != 0) { if (wpa_channel_info(wpa_auth, &ci) != 0) {
wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
"Failed to get channel info to validate received OCI in EAPOL-Key 2/4"); "Failed to get channel info to validate received OCI in EAPOL-Key 2/4");
return; goto out;
} }
if (get_sta_tx_parameters(sm, if (get_sta_tx_parameters(sm,
channel_width_to_int(ci.chanwidth), channel_width_to_int(ci.chanwidth),
ci.seg1_idx, &tx_chanwidth, ci.seg1_idx, &tx_chanwidth,
&tx_seg1_idx) < 0) &tx_seg1_idx) < 0)
return; goto out;
res = ocv_verify_tx_params(kde.oci, kde.oci_len, &ci, res = ocv_verify_tx_params(kde.oci, kde.oci_len, &ci,
tx_chanwidth, tx_seg1_idx); tx_chanwidth, tx_seg1_idx);
@ -3251,7 +3276,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
OCV_FAILURE "addr=" MACSTR OCV_FAILURE "addr=" MACSTR
" frame=eapol-key-m2 error=%s", " frame=eapol-key-m2 error=%s",
MAC2STR(sm->addr), ocv_errorstr); MAC2STR(sm->addr), ocv_errorstr);
return; goto out;
} }
} }
#endif /* CONFIG_OCV */ #endif /* CONFIG_OCV */
@ -3259,7 +3284,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
if (ft && ft_check_msg_2_of_4(wpa_auth, sm, &kde) < 0) { if (ft && ft_check_msg_2_of_4(wpa_auth, sm, &kde) < 0) {
wpa_sta_disconnect(wpa_auth, sm->addr, wpa_sta_disconnect(wpa_auth, sm->addr,
WLAN_REASON_PREV_AUTH_NOT_VALID); WLAN_REASON_PREV_AUTH_NOT_VALID);
return; goto out;
} }
#endif /* CONFIG_IEEE80211R_AP */ #endif /* CONFIG_IEEE80211R_AP */
#ifdef CONFIG_P2P #ifdef CONFIG_P2P
@ -3297,7 +3322,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
"DPP: Peer indicated it supports PFS and local configuration allows this, but PFS was not negotiated for the association"); "DPP: Peer indicated it supports PFS and local configuration allows this, but PFS was not negotiated for the association");
wpa_sta_disconnect(wpa_auth, sm->addr, wpa_sta_disconnect(wpa_auth, sm->addr,
WLAN_REASON_PREV_AUTH_NOT_VALID); WLAN_REASON_PREV_AUTH_NOT_VALID);
return; goto out;
} }
} }
#endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP2 */
@ -3317,7 +3342,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
sm->sup_pmk_r1_name, WPA_PMK_NAME_LEN); sm->sup_pmk_r1_name, WPA_PMK_NAME_LEN);
wpa_hexdump(MSG_DEBUG, "FT: Derived PMKR1Name", wpa_hexdump(MSG_DEBUG, "FT: Derived PMKR1Name",
sm->pmk_r1_name, WPA_PMK_NAME_LEN); sm->pmk_r1_name, WPA_PMK_NAME_LEN);
return; goto out;
} }
} }
#endif /* CONFIG_IEEE80211R_AP */ #endif /* CONFIG_IEEE80211R_AP */
@ -3326,7 +3351,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
wpa_auth_update_vlan(wpa_auth, sm->addr, vlan_id) < 0) { wpa_auth_update_vlan(wpa_auth, sm->addr, vlan_id) < 0) {
wpa_sta_disconnect(wpa_auth, sm->addr, wpa_sta_disconnect(wpa_auth, sm->addr,
WLAN_REASON_PREV_AUTH_NOT_VALID); WLAN_REASON_PREV_AUTH_NOT_VALID);
return; goto out;
} }
sm->pending_1_of_4_timeout = 0; sm->pending_1_of_4_timeout = 0;
@ -3342,9 +3367,20 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
sm->MICVerified = true; sm->MICVerified = true;
#ifdef CONFIG_IEEE80211R_AP
if (wpa_key_mgmt_ft(sm->wpa_key_mgmt) && !sm->ft_completed) {
wpa_printf(MSG_DEBUG, "FT: Store PMK-R0/PMK-R1");
wpa_auth_ft_store_keys(sm, pmk_r0, pmk_r1, pmk_r0_name,
key_len);
}
#endif /* CONFIG_IEEE80211R_AP */
os_memcpy(&sm->PTK, &PTK, sizeof(PTK)); os_memcpy(&sm->PTK, &PTK, sizeof(PTK));
forced_memzero(&PTK, sizeof(PTK)); forced_memzero(&PTK, sizeof(PTK));
sm->PTK_valid = true; sm->PTK_valid = true;
out:
forced_memzero(pmk_r0, sizeof(pmk_r0));
forced_memzero(pmk_r1, sizeof(pmk_r1));
} }

View file

@ -2109,11 +2109,11 @@ int wpa_ft_store_pmk_fils(struct wpa_state_machine *sm,
} }
int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, struct wpa_ptk *ptk) int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, struct wpa_ptk *ptk,
u8 *pmk_r0, u8 *pmk_r1, u8 *pmk_r0_name,
size_t *key_len)
{ {
u8 pmk_r0[PMK_LEN_MAX], pmk_r0_name[WPA_PMK_NAME_LEN];
size_t pmk_r0_len, pmk_r1_len; size_t pmk_r0_len, pmk_r1_len;
u8 pmk_r1[PMK_LEN_MAX];
u8 ptk_name[WPA_PMK_NAME_LEN]; u8 ptk_name[WPA_PMK_NAME_LEN];
const u8 *mdid = sm->wpa_auth->conf.mobility_domain; const u8 *mdid = sm->wpa_auth->conf.mobility_domain;
const u8 *r0kh = sm->wpa_auth->conf.r0_key_holder; const u8 *r0kh = sm->wpa_auth->conf.r0_key_holder;
@ -2121,12 +2121,6 @@ int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, struct wpa_ptk *ptk)
const u8 *r1kh = sm->wpa_auth->conf.r1_key_holder; const u8 *r1kh = sm->wpa_auth->conf.r1_key_holder;
const u8 *ssid = sm->wpa_auth->conf.ssid; const u8 *ssid = sm->wpa_auth->conf.ssid;
size_t ssid_len = sm->wpa_auth->conf.ssid_len; size_t ssid_len = sm->wpa_auth->conf.ssid_len;
int psk_local = sm->wpa_auth->conf.ft_psk_generate_local;
int expires_in = sm->wpa_auth->conf.r0_key_lifetime;
struct vlan_description vlan;
const u8 *identity, *radius_cui;
size_t identity_len, radius_cui_len;
int session_timeout;
const u8 *mpmk; const u8 *mpmk;
size_t mpmk_len; size_t mpmk_len;
@ -2139,7 +2133,7 @@ int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, struct wpa_ptk *ptk)
pmk_r0_len = SHA384_MAC_LEN; pmk_r0_len = SHA384_MAC_LEN;
else else
pmk_r0_len = PMK_LEN; pmk_r0_len = PMK_LEN;
pmk_r1_len = pmk_r0_len; *key_len = pmk_r1_len = pmk_r0_len;
if (sm->xxkey_len > 0) { if (sm->xxkey_len > 0) {
mpmk = sm->xxkey; mpmk = sm->xxkey;
@ -2153,10 +2147,39 @@ int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, struct wpa_ptk *ptk)
return -1; return -1;
} }
if (wpa_derive_pmk_r0(mpmk, mpmk_len, ssid, ssid_len, mdid,
r0kh, r0kh_len, sm->addr,
pmk_r0, pmk_r0_name,
sm->wpa_key_mgmt) < 0 ||
wpa_derive_pmk_r1(pmk_r0, pmk_r0_len, pmk_r0_name, r1kh, sm->addr,
pmk_r1, sm->pmk_r1_name) < 0)
return -1;
return wpa_pmk_r1_to_ptk(pmk_r1, pmk_r1_len, sm->SNonce, sm->ANonce,
sm->addr, sm->wpa_auth->addr, sm->pmk_r1_name,
ptk, ptk_name, sm->wpa_key_mgmt, sm->pairwise,
0);
}
void wpa_auth_ft_store_keys(struct wpa_state_machine *sm, const u8 *pmk_r0,
const u8 *pmk_r1, const u8 *pmk_r0_name,
size_t key_len)
{
int psk_local = sm->wpa_auth->conf.ft_psk_generate_local;
int expires_in = sm->wpa_auth->conf.r0_key_lifetime;
struct vlan_description vlan;
const u8 *identity, *radius_cui;
size_t identity_len, radius_cui_len;
int session_timeout;
if (psk_local && wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt))
return;
if (wpa_ft_get_vlan(sm->wpa_auth, sm->addr, &vlan) < 0) { if (wpa_ft_get_vlan(sm->wpa_auth, sm->addr, &vlan) < 0) {
wpa_printf(MSG_DEBUG, "FT: vlan not available for STA " MACSTR, wpa_printf(MSG_DEBUG, "FT: vlan not available for STA " MACSTR,
MAC2STR(sm->addr)); MAC2STR(sm->addr));
return -1; return;
} }
identity_len = wpa_ft_get_identity(sm->wpa_auth, sm->addr, &identity); identity_len = wpa_ft_get_identity(sm->wpa_auth, sm->addr, &identity);
@ -2164,31 +2187,16 @@ int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, struct wpa_ptk *ptk)
&radius_cui); &radius_cui);
session_timeout = wpa_ft_get_session_timeout(sm->wpa_auth, sm->addr); session_timeout = wpa_ft_get_session_timeout(sm->wpa_auth, sm->addr);
if (wpa_derive_pmk_r0(mpmk, mpmk_len, ssid, ssid_len, mdid,
r0kh, r0kh_len, sm->addr, wpa_ft_store_pmk_r0(sm->wpa_auth, sm->addr, pmk_r0, key_len,
pmk_r0, pmk_r0_name,
sm->wpa_key_mgmt) < 0)
return -1;
if (!psk_local || !wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt))
wpa_ft_store_pmk_r0(sm->wpa_auth, sm->addr, pmk_r0, pmk_r0_len,
pmk_r0_name, pmk_r0_name,
sm->pairwise, &vlan, expires_in, sm->pairwise, &vlan, expires_in,
session_timeout, identity, identity_len, session_timeout, identity, identity_len,
radius_cui, radius_cui_len); radius_cui, radius_cui_len);
wpa_ft_store_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1, key_len,
if (wpa_derive_pmk_r1(pmk_r0, pmk_r0_len, pmk_r0_name, r1kh, sm->addr,
pmk_r1, sm->pmk_r1_name) < 0)
return -1;
if (!psk_local || !wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt))
wpa_ft_store_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1, pmk_r1_len,
sm->pmk_r1_name, sm->pairwise, &vlan, sm->pmk_r1_name, sm->pairwise, &vlan,
expires_in, session_timeout, identity, expires_in, session_timeout, identity,
identity_len, radius_cui, radius_cui_len); identity_len, radius_cui, radius_cui_len);
return wpa_pmk_r1_to_ptk(pmk_r1, pmk_r1_len, sm->SNonce, sm->ANonce,
sm->addr, sm->wpa_auth->addr, sm->pmk_r1_name,
ptk, ptk_name, sm->wpa_key_mgmt, sm->pairwise,
0);
} }

View file

@ -304,7 +304,12 @@ int wpa_write_ftie(struct wpa_auth_config *conf, int key_mgmt, size_t key_len,
const u8 *anonce, const u8 *snonce, const u8 *anonce, const u8 *snonce,
u8 *buf, size_t len, const u8 *subelem, u8 *buf, size_t len, const u8 *subelem,
size_t subelem_len, int rsnxe_used); size_t subelem_len, int rsnxe_used);
int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, struct wpa_ptk *ptk); int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, struct wpa_ptk *ptk,
u8 *pmk_r0, u8 *pmk_r1, u8 *pmk_r0_name,
size_t *key_len);
void wpa_auth_ft_store_keys(struct wpa_state_machine *sm, const u8 *pmk_r0,
const u8 *pmk_r1, const u8 *pmk_r0_name,
size_t key_len);
struct wpa_ft_pmk_cache * wpa_ft_pmk_cache_init(void); struct wpa_ft_pmk_cache * wpa_ft_pmk_cache_init(void);
void wpa_ft_pmk_cache_deinit(struct wpa_ft_pmk_cache *cache); void wpa_ft_pmk_cache_deinit(struct wpa_ft_pmk_cache *cache);
void wpa_ft_install_ptk(struct wpa_state_machine *sm, int retry); void wpa_ft_install_ptk(struct wpa_state_machine *sm, int retry);