Last active
June 21, 2023 15:49
-
-
Save zekica/bee8df4144d097f2e07bcaaca96de4b8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c | |
index cb6595f..571a483 100644 | |
--- a/src/ap/wpa_auth.c | |
+++ b/src/ap/wpa_auth.c | |
@@ -56,7 +56,9 @@ static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth, | |
struct wpa_group *group); | |
static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce, | |
const u8 *pmk, unsigned int pmk_len, | |
- struct wpa_ptk *ptk); | |
+ struct wpa_ptk *ptk, | |
+ u8 *pmk_r0, u8 *pmk_r1, u8 *pmk_r0_name, | |
+ size_t *key_len); | |
static void wpa_group_free(struct wpa_authenticator *wpa_auth, | |
struct wpa_group *group); | |
static void wpa_group_get(struct wpa_authenticator *wpa_auth, | |
@@ -879,6 +881,10 @@ static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data, | |
const u8 *pmk = NULL; | |
size_t pmk_len; | |
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)); | |
for (;;) { | |
@@ -900,7 +906,8 @@ static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data, | |
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, | |
+ pmk_r0, pmk_r1, pmk_r0_name, &key_len) < 0) | |
break; | |
if (wpa_verify_key_mic(sm->wpa_key_mgmt, pmk_len, &PTK, | |
@@ -921,7 +928,7 @@ static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data, | |
if (!ok) { | |
wpa_printf(MSG_DEBUG, | |
"WPA: Earlier SNonce did not result in matching MIC"); | |
- return -1; | |
+ goto fail; | |
} | |
wpa_printf(MSG_DEBUG, | |
@@ -930,14 +937,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) && | |
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->PTK, &PTK, sizeof(PTK)); | |
forced_memzero(&PTK, sizeof(PTK)); | |
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; | |
} | |
@@ -2208,7 +2227,9 @@ SM_STATE(WPA_PTK, PTKSTART) | |
static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce, | |
const u8 *pmk, unsigned int pmk_len, | |
- struct wpa_ptk *ptk) | |
+ struct wpa_ptk *ptk, | |
+ u8 *pmk_r0, u8 *pmk_r1, u8 *pmk_r0_name, | |
+ size_t *key_len) | |
{ | |
const u8 *z = NULL; | |
size_t z_len = 0; | |
@@ -2226,7 +2247,8 @@ static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce, | |
sm->wpa_key_mgmt, | |
sm->pairwise); | |
} | |
- return wpa_auth_derive_ptk_ft(sm, ptk); | |
+ return wpa_auth_derive_ptk_ft(sm, ptk, pmk_r0, pmk_r1, | |
+ pmk_r0_name, key_len); | |
} | |
#endif /* CONFIG_IEEE80211R_AP */ | |
@@ -2819,6 +2841,9 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) | |
struct wpa_eapol_key *key; | |
struct wpa_eapol_ie_parse kde; | |
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; | |
SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING, wpa_ptk); | |
sm->EAPOLKeyReceived = FALSE; | |
@@ -2856,7 +2881,8 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) | |
pmk_len = sm->pmksa->pmk_len; | |
} | |
- if (wpa_derive_ptk(sm, sm->SNonce, pmk, pmk_len, &PTK) < 0) | |
+ if (wpa_derive_ptk(sm, sm->SNonce, pmk, pmk_len, &PTK, pmk_r0, pmk_r1, | |
+ pmk_r0_name, &key_len) < 0) | |
break; | |
if (mic_len && | |
@@ -2890,7 +2916,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) | |
"invalid MIC in msg 2/4 of 4-Way Handshake"); | |
if (psk_found) | |
wpa_auth_psk_failure_report(sm->wpa_auth, sm->addr); | |
- return; | |
+ goto out; | |
} | |
/* | |
@@ -2904,12 +2930,12 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) | |
key_data_length = WPA_GET_BE16(mic + mic_len); | |
if (key_data_length > sm->last_rx_eapol_key_len - sizeof(*hdr) - | |
sizeof(*key) - mic_len - 2) | |
- return; | |
+ goto out; | |
if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) { | |
wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, | |
"received EAPOL-Key msg 2/4 with invalid Key Data contents"); | |
- return; | |
+ goto out; | |
} | |
if (kde.rsn_ie) { | |
eapol_key_ie = kde.rsn_ie; | |
@@ -2936,7 +2962,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) | |
/* MLME-DEAUTHENTICATE.request */ | |
wpa_sta_disconnect(wpa_auth, sm->addr, | |
WLAN_REASON_PREV_AUTH_NOT_VALID); | |
- return; | |
+ goto out; | |
} | |
#ifdef CONFIG_OCV | |
if (wpa_auth_uses_ocv(sm)) { | |
@@ -2947,20 +2973,20 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) | |
if (wpa_channel_info(wpa_auth, &ci) != 0) { | |
wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, | |
"Failed to get channel info to validate received OCI in EAPOL-Key 2/4"); | |
- return; | |
+ goto out; | |
} | |
if (get_sta_tx_parameters(sm, | |
channel_width_to_int(ci.chanwidth), | |
ci.seg1_idx, &tx_chanwidth, | |
&tx_seg1_idx) < 0) | |
- return; | |
+ goto out; | |
if (ocv_verify_tx_params(kde.oci, kde.oci_len, &ci, | |
tx_chanwidth, tx_seg1_idx) != 0) { | |
wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, | |
ocv_errorstr); | |
- return; | |
+ goto out; | |
} | |
} | |
#endif /* CONFIG_OCV */ | |
@@ -2968,7 +2994,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) | |
if (ft && ft_check_msg_2_of_4(wpa_auth, sm, &kde) < 0) { | |
wpa_sta_disconnect(wpa_auth, sm->addr, | |
WLAN_REASON_PREV_AUTH_NOT_VALID); | |
- return; | |
+ goto out; | |
} | |
#endif /* CONFIG_IEEE80211R_AP */ | |
#ifdef CONFIG_P2P | |
@@ -3016,7 +3042,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) | |
wpa_auth_update_vlan(wpa_auth, sm->addr, vlan_id) < 0) { | |
wpa_sta_disconnect(wpa_auth, sm->addr, | |
WLAN_REASON_PREV_AUTH_NOT_VALID); | |
- return; | |
+ goto out; | |
} | |
sm->pending_1_of_4_timeout = 0; | |
@@ -3031,10 +3057,20 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) | |
} | |
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)); | |
forced_memzero(&PTK, sizeof(PTK)); | |
sm->PTK_valid = TRUE; | |
+out: | |
+ forced_memzero(pmk_r0, sizeof(pmk_r0)); | |
+ forced_memzero(pmk_r1, sizeof(pmk_r1)); | |
} | |
diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c | |
index 696f8d5..71b3599 100644 | |
--- a/src/ap/wpa_auth_ft.c | |
+++ b/src/ap/wpa_auth_ft.c | |
@@ -2075,13 +2075,14 @@ 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 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt) ? | |
SHA384_MAC_LEN : PMK_LEN; | |
size_t pmk_r1_len = pmk_r0_len; | |
- u8 pmk_r1[PMK_LEN_MAX]; | |
+ *key_len = pmk_r1_len; | |
u8 ptk_name[WPA_PMK_NAME_LEN]; | |
const u8 *mdid = sm->wpa_auth->conf.mobility_domain; | |
const u8 *r0kh = sm->wpa_auth->conf.r0_key_holder; | |
@@ -2089,12 +2090,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 *ssid = sm->wpa_auth->conf.ssid; | |
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; | |
size_t mpmk_len; | |
@@ -2109,11 +2104,39 @@ int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, struct wpa_ptk *ptk) | |
"derivation"); | |
return -1; | |
} | |
+ if (wpa_derive_pmk_r0(mpmk, mpmk_len, ssid, ssid_len, mdid, | |
+ r0kh, r0kh_len, sm->addr, | |
+ pmk_r0, pmk_r0_name, | |
+ wpa_key_mgmt_sha384(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); | |
+} | |
+ | |
+ | |
+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) { | |
wpa_printf(MSG_DEBUG, "FT: vlan not available for STA " MACSTR, | |
MAC2STR(sm->addr)); | |
- return -1; | |
+ return; | |
} | |
identity_len = wpa_ft_get_identity(sm->wpa_auth, sm->addr, &identity); | |
@@ -2121,35 +2144,16 @@ int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, struct wpa_ptk *ptk) | |
&radius_cui); | |
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, | |
- pmk_r0, pmk_r0_name, | |
- wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) < 0) | |
- return -1; | |
- wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", pmk_r0, pmk_r0_len); | |
- wpa_hexdump(MSG_DEBUG, "FT: PMKR0Name", pmk_r0_name, WPA_PMK_NAME_LEN); | |
- 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, | |
- sm->pairwise, &vlan, expires_in, | |
- session_timeout, identity, identity_len, | |
- radius_cui, radius_cui_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; | |
- wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", pmk_r1, pmk_r1_len); | |
- wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", sm->pmk_r1_name, | |
- WPA_PMK_NAME_LEN); | |
- 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, | |
- expires_in, session_timeout, identity, | |
- identity_len, radius_cui, radius_cui_len); | |
+ wpa_ft_store_pmk_r0(sm->wpa_auth, sm->addr, pmk_r0, key_len, | |
+ pmk_r0_name, | |
+ sm->pairwise, &vlan, expires_in, | |
+ session_timeout, identity, identity_len, | |
+ radius_cui, radius_cui_len); | |
+ wpa_ft_store_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1, key_len, | |
+ sm->pmk_r1_name, sm->pairwise, &vlan, | |
+ expires_in, session_timeout, identity, | |
+ 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); | |
} | |
diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h | |
index 4babd0c..2bc1674 100644 | |
--- a/src/ap/wpa_auth_i.h | |
+++ b/src/ap/wpa_auth_i.h | |
@@ -292,7 +292,12 @@ int wpa_write_ftie(struct wpa_auth_config *conf, int use_sha384, | |
const u8 *anonce, const u8 *snonce, | |
u8 *buf, size_t len, const u8 *subelem, | |
size_t subelem_len); | |
-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); | |
void wpa_ft_pmk_cache_deinit(struct wpa_ft_pmk_cache *cache); | |
void wpa_ft_install_ptk(struct wpa_state_machine *sm); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment