mirror of
https://github.com/espressif/esp-idf.git
synced 2026-08-18 06:35:35 +03:00
fix(esp_wifi): Add alt snonce verification in softAP
This commit is contained in:
@@ -43,6 +43,10 @@
|
||||
|
||||
|
||||
static int wpa_sm_step(struct wpa_state_machine *sm);
|
||||
static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
|
||||
const u8 *pmk, unsigned int pmk_len, struct wpa_ptk *ptk);
|
||||
static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data,
|
||||
size_t data_len);
|
||||
static int wpa_verify_key_mic(int akmp, struct wpa_ptk *PTK, u8 *data,
|
||||
size_t data_len);
|
||||
static void wpa_group_sm_step(struct wpa_authenticator *wpa_auth,
|
||||
@@ -733,6 +737,14 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, struct wpa_state_machine *s
|
||||
!wpa_replay_counter_valid(sm->key_replay, key->replay_counter)) {
|
||||
int i;
|
||||
|
||||
if (msg == PAIRWISE_4 && sm->alt_snonce_valid &&
|
||||
sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING &&
|
||||
os_memcmp(key->replay_counter, sm->alt_replay_counter,
|
||||
WPA_REPLAY_COUNTER_LEN) == 0) {
|
||||
wpa_printf(MSG_DEBUG, "WPA: Try to process received EAPOL-Key 4/4 based on old Replay Counter and SNonce from an earlier EAPOL-Key 1/4");
|
||||
goto continue_processing;
|
||||
}
|
||||
|
||||
if (msg == PAIRWISE_2 &&
|
||||
wpa_replay_counter_valid(sm->prev_key_replay,
|
||||
key->replay_counter) &&
|
||||
@@ -746,9 +758,12 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, struct wpa_state_machine *s
|
||||
* pending requests, so allow the SNonce to be updated
|
||||
* even if we have already sent out EAPOL-Key 3/4.
|
||||
*/
|
||||
wpa_printf(MSG_DEBUG, "Process SNonce update from STA based on retransmitted EAPOL-Key 1/4");
|
||||
sm->update_snonce = 1;
|
||||
wpa_replay_counter_mark_invalid(sm->prev_key_replay,
|
||||
key->replay_counter);
|
||||
os_memcpy(sm->alt_SNonce, sm->SNonce, WPA_NONCE_LEN);
|
||||
sm->alt_snonce_valid = TRUE;
|
||||
os_memcpy(sm->alt_replay_counter, sm->key_replay[0].counter,
|
||||
WPA_REPLAY_COUNTER_LEN);
|
||||
goto continue_processing;
|
||||
}
|
||||
|
||||
@@ -862,7 +877,9 @@ continue_processing:
|
||||
sm->MICVerified = FALSE;
|
||||
if (sm->PTK_valid && !sm->update_snonce) {
|
||||
if (wpa_verify_key_mic(sm->wpa_key_mgmt, &sm->PTK, data,
|
||||
data_len)) {
|
||||
data_len) &&
|
||||
(msg != PAIRWISE_4 || !sm->alt_snonce_valid ||
|
||||
wpa_try_alt_snonce(sm, data, data_len))) {
|
||||
wpa_printf(MSG_INFO,
|
||||
"received EAPOL-Key with invalid MIC");
|
||||
return;
|
||||
@@ -1210,6 +1227,56 @@ static void wpa_send_eapol(struct wpa_authenticator *wpa_auth,
|
||||
eloop_register_timeout(1, 0, resend_eapol_handle, (void*)(sm->index), NULL);
|
||||
}
|
||||
|
||||
static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data,
|
||||
size_t data_len)
|
||||
{
|
||||
struct wpa_ptk PTK;
|
||||
int ok = 0;
|
||||
const u8 *pmk = NULL;
|
||||
unsigned int pmk_len;
|
||||
|
||||
os_memset(&PTK, 0, sizeof(PTK));
|
||||
for (;;) {
|
||||
if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
|
||||
!wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
|
||||
pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, pmk);
|
||||
if (pmk == NULL)
|
||||
break;
|
||||
pmk_len = PMK_LEN;
|
||||
} else {
|
||||
pmk = sm->PMK;
|
||||
pmk_len = sm->pmk_len;
|
||||
}
|
||||
|
||||
if (!pmk && sm->pmksa) {
|
||||
pmk = sm->pmksa->pmk;
|
||||
pmk_len = sm->pmksa->pmk_len;
|
||||
}
|
||||
|
||||
wpa_derive_ptk(sm, sm->alt_SNonce, pmk, pmk_len, &PTK);
|
||||
|
||||
if (wpa_verify_key_mic(sm->wpa_key_mgmt, &PTK, data, data_len) == 0) {
|
||||
ok = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
|
||||
wpa_key_mgmt_sae(sm->wpa_key_mgmt))
|
||||
break;
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
wpa_printf(MSG_DEBUG, "WPA: Verified Key MIC using alt_SNonce");
|
||||
os_memcpy(&sm->PTK, &PTK, sizeof(PTK));
|
||||
sm->PTK_valid = TRUE;
|
||||
os_memcpy(sm->SNonce, sm->alt_SNonce, WPA_NONCE_LEN);
|
||||
sm->alt_snonce_valid = FALSE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int wpa_verify_key_mic(int akmp, struct wpa_ptk *PTK, u8 *data,
|
||||
size_t data_len)
|
||||
{
|
||||
@@ -1246,6 +1313,7 @@ void wpa_remove_ptk(struct wpa_state_machine *sm)
|
||||
memset(&sm->PTK, 0, sizeof(sm->PTK));
|
||||
wpa_auth_set_key(sm->wpa_auth, 0, WIFI_WPA_ALG_NONE, sm->addr, 0, NULL, 0);
|
||||
sm->pairwise_set = FALSE;
|
||||
sm->alt_snonce_valid = FALSE;
|
||||
eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm);
|
||||
}
|
||||
|
||||
|
||||
@@ -86,6 +86,7 @@ struct wpa_state_machine {
|
||||
unsigned int mgmt_frame_prot:1;
|
||||
unsigned int rx_eapol_key_secure:1;
|
||||
unsigned int update_snonce:1;
|
||||
unsigned int alt_snonce_valid:1;
|
||||
#ifdef CONFIG_IEEE80211R_AP
|
||||
unsigned int ft_completed:1;
|
||||
unsigned int pmk_r1_name_valid:1;
|
||||
@@ -96,6 +97,9 @@ struct wpa_state_machine {
|
||||
u8 req_replay_counter[WPA_REPLAY_COUNTER_LEN];
|
||||
int req_replay_counter_used;
|
||||
|
||||
u8 alt_SNonce[WPA_NONCE_LEN];
|
||||
u8 alt_replay_counter[WPA_REPLAY_COUNTER_LEN];
|
||||
|
||||
u8 *wpa_ie;
|
||||
size_t wpa_ie_len;
|
||||
u8 *rsnxe;
|
||||
|
||||
Reference in New Issue
Block a user