aboutsummaryrefslogtreecommitdiff
path: root/src/ap/wpa_auth.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ap/wpa_auth.c')
-rw-r--r--src/ap/wpa_auth.c687
1 files changed, 513 insertions, 174 deletions
diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index bb7ee254..635a74a6 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -1,6 +1,6 @@
/*
* IEEE 802.11 RSN / WPA Authenticator
- * Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2022, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -23,6 +23,7 @@
#include "crypto/sha1.h"
#include "crypto/sha256.h"
#include "crypto/sha384.h"
+#include "crypto/sha512.h"
#include "crypto/random.h"
#include "eapol_auth/eapol_auth_sm.h"
#include "drivers/driver.h"
@@ -35,7 +36,7 @@
#define STATE_MACHINE_DATA struct wpa_state_machine
#define STATE_MACHINE_DEBUG_PREFIX "WPA"
-#define STATE_MACHINE_ADDR sm->addr
+#define STATE_MACHINE_ADDR wpa_auth_get_spa(sm)
static void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx);
@@ -58,7 +59,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, 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,
struct wpa_group *group);
static void wpa_group_get(struct wpa_authenticator *wpa_auth,
@@ -79,6 +82,18 @@ static const int dot11RSNAConfigPMKReauthThreshold = 70;
static const int dot11RSNAConfigSATimeout = 60;
+static const u8 * wpa_auth_get_aa(const struct wpa_state_machine *sm)
+{
+ return sm->wpa_auth->addr;
+}
+
+
+static const u8 * wpa_auth_get_spa(const struct wpa_state_machine *sm)
+{
+ return sm->addr;
+}
+
+
static inline int wpa_auth_mic_failure_report(
struct wpa_authenticator *wpa_auth, const u8 *addr)
{
@@ -149,6 +164,20 @@ static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth,
}
+#ifdef CONFIG_PASN
+static inline int wpa_auth_set_ltf_keyseed(struct wpa_authenticator *wpa_auth,
+ const u8 *peer_addr,
+ const u8 *ltf_keyseed,
+ size_t ltf_keyseed_len)
+{
+ if (!wpa_auth->cb->set_ltf_keyseed)
+ return -1;
+ return wpa_auth->cb->set_ltf_keyseed(wpa_auth->cb_ctx, peer_addr,
+ ltf_keyseed, ltf_keyseed_len);
+}
+#endif /* CONFIG_PASN */
+
+
static inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth,
const u8 *addr, int idx, u8 *seq)
{
@@ -238,13 +267,14 @@ void wpa_auth_store_ptksa(struct wpa_authenticator *wpa_auth,
}
-void wpa_auth_remove_ptksa(struct wpa_authenticator *wpa_auth,
- const u8 *addr, int cipher)
+static void wpa_auth_remove_ptksa(struct wpa_authenticator *wpa_auth,
+ const u8 *addr, int cipher)
{
if (wpa_auth->cb->clear_ptksa)
wpa_auth->cb->clear_ptksa(wpa_auth->cb_ctx, addr, cipher);
}
+
void wpa_auth_logger(struct wpa_authenticator *wpa_auth, const u8 *addr,
logger_level level, const char *txt)
{
@@ -363,7 +393,8 @@ static void wpa_rekey_ptk(void *eloop_ctx, void *timeout_ctx)
struct wpa_authenticator *wpa_auth = eloop_ctx;
struct wpa_state_machine *sm = timeout_ctx;
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "rekeying PTK");
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
+ "rekeying PTK");
wpa_request_new_ptk(sm);
wpa_sm_step(sm);
}
@@ -373,7 +404,8 @@ void wpa_auth_set_ptk_rekey_timer(struct wpa_state_machine *sm)
{
if (sm && sm->wpa_auth->conf.wpa_ptk_rekey) {
wpa_printf(MSG_DEBUG, "WPA: Start PTK rekeying timer for "
- MACSTR " (%d seconds)", MAC2STR(sm->addr),
+ MACSTR " (%d seconds)",
+ MAC2STR(wpa_auth_get_spa(sm)),
sm->wpa_auth->conf.wpa_ptk_rekey);
eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm);
eloop_register_timeout(sm->wpa_auth->conf.wpa_ptk_rekey, 0,
@@ -607,7 +639,7 @@ void wpa_deinit(struct wpa_authenticator *wpa_auth)
while (group) {
prev = group;
group = group->next;
- os_free(prev);
+ bin_clear_free(prev, sizeof(*prev));
}
os_free(wpa_auth);
@@ -680,7 +712,7 @@ int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth,
#ifdef CONFIG_IEEE80211R_AP
if (sm->ft_completed) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
"FT authentication already completed - do not start 4-way handshake");
/* Go to PTKINITDONE state to allow GTK rekeying */
sm->wpa_ptk_state = WPA_PTK_PTKINITDONE;
@@ -691,7 +723,7 @@ int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth,
#ifdef CONFIG_FILS
if (sm->fils_completed) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
"FILS authentication already completed - do not start 4-way handshake");
/* Go to PTKINITDONE state to allow GTK rekeying */
sm->wpa_ptk_state = WPA_PTK_PTKINITDONE;
@@ -706,7 +738,7 @@ int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth,
return wpa_sm_step(sm);
}
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
"start authentication");
sm->started = 1;
@@ -735,16 +767,14 @@ static void wpa_free_sta_sm(struct wpa_state_machine *sm)
{
#ifdef CONFIG_P2P
if (WPA_GET_BE32(sm->ip_addr)) {
- u32 start;
wpa_printf(MSG_DEBUG,
"P2P: Free assigned IP address %u.%u.%u.%u from "
- MACSTR,
+ MACSTR " (bit %u)",
sm->ip_addr[0], sm->ip_addr[1],
sm->ip_addr[2], sm->ip_addr[3],
- MAC2STR(sm->addr));
- start = WPA_GET_BE32(sm->wpa_auth->conf.ip_addr_start);
- bitfield_clear(sm->wpa_auth->ip_pool,
- WPA_GET_BE32(sm->ip_addr) - start);
+ MAC2STR(wpa_auth_get_spa(sm)),
+ sm->ip_addr_bit);
+ bitfield_clear(sm->wpa_auth->ip_pool, sm->ip_addr_bit);
}
#endif /* CONFIG_P2P */
if (sm->GUpdateStationKeys) {
@@ -775,7 +805,7 @@ void wpa_auth_sta_deinit(struct wpa_state_machine *sm)
wpa_auth = sm->wpa_auth;
if (wpa_auth->conf.wpa_strict_rekey && sm->has_GTK) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
"strict rekeying - force GTK rekey since STA is leaving");
if (eloop_deplete_timeout(0, 500000, wpa_rekey_gtk,
wpa_auth, NULL) == -1)
@@ -795,7 +825,7 @@ void wpa_auth_sta_deinit(struct wpa_state_machine *sm)
* Freeing will be completed in the end of wpa_sm_step(). */
wpa_printf(MSG_DEBUG,
"WPA: Registering pending STA state machine deinit for "
- MACSTR, MAC2STR(sm->addr));
+ MACSTR, MAC2STR(wpa_auth_get_spa(sm)));
sm->pending_deinit = 1;
} else
wpa_free_sta_sm(sm);
@@ -810,7 +840,7 @@ static void wpa_request_new_ptk(struct wpa_state_machine *sm)
if (!sm->use_ext_key_id && sm->wpa_auth->conf.wpa_deny_ptk0_rekey) {
wpa_printf(MSG_INFO,
"WPA: PTK0 rekey not allowed, disconnect " MACSTR,
- MAC2STR(sm->addr));
+ MAC2STR(wpa_auth_get_spa(sm)));
sm->Disconnect = true;
/* Try to encourage the STA to reconnect */
sm->disconnect_reason =
@@ -908,18 +938,19 @@ static int wpa_receive_error_report(struct wpa_authenticator *wpa_auth,
struct wpa_state_machine *sm, int group)
{
/* Supplicant reported a Michael MIC error */
- wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
"received EAPOL-Key Error Request (STA detected Michael MIC failure (group=%d))",
group);
if (group && wpa_auth->conf.wpa_group != WPA_CIPHER_TKIP) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
"ignore Michael MIC failure report since group cipher is not TKIP");
} else if (!group && sm->pairwise != WPA_CIPHER_TKIP) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
"ignore Michael MIC failure report since pairwise cipher is not TKIP");
} else {
- if (wpa_auth_mic_failure_report(wpa_auth, sm->addr) > 0)
+ if (wpa_auth_mic_failure_report(wpa_auth,
+ wpa_auth_get_spa(sm)) > 0)
return 1; /* STA entry was removed */
sm->dot11RSNAStatsTKIPRemoteMICFailures++;
wpa_auth->dot11RSNAStatsTKIPRemoteMICFailures++;
@@ -942,6 +973,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 (;;) {
@@ -963,8 +998,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) <
- 0)
+ if (wpa_derive_ptk(sm, sm->alt_SNonce, pmk, pmk_len, &PTK, 0,
+ pmk_r0, pmk_r1, pmk_r0_name, &key_len) < 0)
break;
if (wpa_verify_key_mic(sm->wpa_key_mgmt, pmk_len, &PTK,
@@ -985,7 +1020,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,
@@ -994,14 +1029,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;
}
@@ -1051,7 +1098,7 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
key_data_length = WPA_GET_BE16(mic + mic_len);
wpa_printf(MSG_DEBUG, "WPA: Received EAPOL-Key from " MACSTR
" key_info=0x%x type=%u mic_len=%zu key_data_length=%u",
- MAC2STR(sm->addr), key_info, key->type,
+ MAC2STR(wpa_auth_get_spa(sm)), key_info, key->type,
mic_len, key_data_length);
wpa_hexdump(MSG_MSGDUMP,
"WPA: EAPOL-Key header (ending before Key MIC)",
@@ -1126,7 +1173,7 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
if (wpa_use_cmac(sm->wpa_key_mgmt) &&
!wpa_use_akm_defined(sm->wpa_key_mgmt) &&
ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) {
- wpa_auth_logger(wpa_auth, sm->addr,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
LOGGER_WARNING,
"advertised support for AES-128-CMAC, but did not use it");
return;
@@ -1135,7 +1182,7 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
if (!wpa_use_cmac(sm->wpa_key_mgmt) &&
!wpa_use_akm_defined(sm->wpa_key_mgmt) &&
ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
- wpa_auth_logger(wpa_auth, sm->addr,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
LOGGER_WARNING,
"did not use HMAC-SHA1-AES with CCMP/GCMP");
return;
@@ -1144,7 +1191,8 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
if (wpa_use_akm_defined(sm->wpa_key_mgmt) &&
ver != WPA_KEY_INFO_TYPE_AKM_DEFINED) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_WARNING,
"did not use EAPOL-Key descriptor version 0 as required for AKM-defined cases");
return;
}
@@ -1154,7 +1202,8 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
if (sm->req_replay_counter_used &&
os_memcmp(key->replay_counter, sm->req_replay_counter,
WPA_REPLAY_COUNTER_LEN) <= 0) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_WARNING,
"received EAPOL-Key request with replayed counter");
return;
}
@@ -1177,7 +1226,8 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
* pending requests, so allow the SNonce to be updated
* even if we have already sent out EAPOL-Key 3/4.
*/
- wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_DEBUG,
"Process SNonce update from STA based on retransmitted EAPOL-Key 1/4");
sm->update_snonce = 1;
os_memcpy(sm->alt_SNonce, sm->SNonce, WPA_NONCE_LEN);
@@ -1197,7 +1247,8 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
* there was two EAPOL-Key 2/4 messages and they had
* different SNonce values.
*/
- wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_DEBUG,
"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;
}
@@ -1206,11 +1257,13 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
wpa_replay_counter_valid(sm->prev_key_replay,
key->replay_counter) &&
sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING) {
- wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_DEBUG,
"ignore retransmitted EAPOL-Key %s - SNonce did not change",
msgtxt);
} else {
- wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_DEBUG,
"received EAPOL-Key %s with unexpected replay counter",
msgtxt);
}
@@ -1230,7 +1283,7 @@ continue_processing:
#ifdef CONFIG_FILS
if (sm->wpa == WPA_VERSION_WPA2 && mic_len == 0 &&
!(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
- wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
"WPA: Encr Key Data bit not set even though AEAD cipher is supposed to be used - drop frame");
return;
}
@@ -1242,7 +1295,8 @@ continue_processing:
sm->wpa_ptk_state != WPA_PTK_PTKCALCNEGOTIATING &&
(!sm->update_snonce ||
sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING)) {
- wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_INFO,
"received EAPOL-Key msg 2/4 in invalid state (%d) - dropped",
sm->wpa_ptk_state);
return;
@@ -1269,7 +1323,8 @@ continue_processing:
case PAIRWISE_4:
if (sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING ||
!sm->PTK_valid) {
- wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_INFO,
"received EAPOL-Key msg 4/4 in invalid state (%d) - dropped",
sm->wpa_ptk_state);
return;
@@ -1278,7 +1333,8 @@ continue_processing:
case GROUP_2:
if (sm->wpa_ptk_group_state != WPA_PTK_GROUP_REKEYNEGOTIATING
|| !sm->PTK_valid) {
- wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_INFO,
"received EAPOL-Key msg 2/2 in invalid state (%d) - dropped",
sm->wpa_ptk_group_state);
return;
@@ -1288,18 +1344,18 @@ continue_processing:
break;
}
- wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
"received EAPOL-Key frame (%s)", msgtxt);
if (key_info & WPA_KEY_INFO_ACK) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
"received invalid EAPOL-Key: Key Ack set");
return;
}
if (!wpa_key_mgmt_fils(sm->wpa_key_mgmt) &&
!(key_info & WPA_KEY_INFO_MIC)) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
"received invalid EAPOL-Key: Key MIC not set");
return;
}
@@ -1307,7 +1363,7 @@ continue_processing:
#ifdef CONFIG_FILS
if (wpa_key_mgmt_fils(sm->wpa_key_mgmt) &&
(key_info & WPA_KEY_INFO_MIC)) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
"received invalid EAPOL-Key: Key MIC set");
return;
}
@@ -1320,7 +1376,8 @@ continue_processing:
data, data_len) &&
(msg != PAIRWISE_4 || !sm->alt_snonce_valid ||
wpa_try_alt_snonce(sm, data, data_len))) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_INFO,
"received EAPOL-Key with invalid MIC");
#ifdef TEST_FUZZ
wpa_printf(MSG_INFO,
@@ -1333,7 +1390,8 @@ continue_processing:
if (!mic_len &&
wpa_aead_decrypt(sm, &sm->PTK, data, data_len,
&key_data_length) < 0) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_INFO,
"received EAPOL-Key with invalid MIC");
#ifdef TEST_FUZZ
wpa_printf(MSG_INFO,
@@ -1357,7 +1415,8 @@ continue_processing:
os_memcpy(sm->req_replay_counter, key->replay_counter,
WPA_REPLAY_COUNTER_LEN);
} else {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_INFO,
"received EAPOL-Key request with invalid MIC");
return;
}
@@ -1373,7 +1432,8 @@ continue_processing:
!(key_info & WPA_KEY_INFO_KEY_TYPE)) > 0)
return; /* STA entry was removed */
} else if (key_info & WPA_KEY_INFO_KEY_TYPE) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_INFO,
"received EAPOL-Key Request for new 4-Way Handshake");
wpa_request_new_ptk(sm);
} else if (key_data_length > 0 &&
@@ -1381,7 +1441,8 @@ continue_processing:
&kde) == 0 &&
kde.mac_addr) {
} else {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_INFO,
"received EAPOL-Key Request for GTK rekeying");
eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL);
if (wpa_auth_gtk_rekey_in_process(wpa_auth))
@@ -1485,8 +1546,15 @@ static void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx)
struct wpa_authenticator *wpa_auth = eloop_ctx;
struct wpa_state_machine *sm = timeout_ctx;
+ if (sm->waiting_radius_psk) {
+ wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
+ "Ignore EAPOL-Key timeout while waiting for RADIUS PSK");
+ return;
+ }
+
sm->pending_1_of_4_timeout = 0;
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "EAPOL-Key timeout");
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
+ "EAPOL-Key timeout");
sm->TimeoutEvt = true;
wpa_sm_step(sm);
}
@@ -1635,22 +1703,25 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
if (pad_len)
*pos++ = 0xdd;
- wpa_hexdump_key(MSG_DEBUG, "Plaintext EAPOL-Key Key Data",
+ wpa_hexdump_key(MSG_DEBUG,
+ "Plaintext EAPOL-Key Key Data (+ padding)",
buf, key_data_len);
if (version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
wpa_use_aes_key_wrap(sm->wpa_key_mgmt) ||
version == WPA_KEY_INFO_TYPE_AES_128_CMAC) {
- wpa_printf(MSG_DEBUG,
- "WPA: Encrypt Key Data using AES-WRAP (KEK length %zu)",
- sm->PTK.kek_len);
+ wpa_hexdump_key(MSG_DEBUG, "RSN: AES-WRAP using KEK",
+ sm->PTK.kek, sm->PTK.kek_len);
if (aes_wrap(sm->PTK.kek, sm->PTK.kek_len,
(key_data_len - 8) / 8, buf, key_data)) {
os_free(hdr);
- os_free(buf);
+ bin_clear_free(buf, key_data_len);
return;
}
+ wpa_hexdump(MSG_DEBUG,
+ "RSN: Encrypted Key Data from AES-WRAP",
+ key_data, key_data_len);
WPA_PUT_BE16(key_mic + mic_len, key_data_len);
-#ifndef CONFIG_NO_RC4
+#if !defined(CONFIG_NO_RC4) && !defined(CONFIG_FIPS)
} else if (sm->PTK.kek_len == 16) {
u8 ek[32];
@@ -1664,18 +1735,19 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
os_memcpy(key_data, buf, key_data_len);
rc4_skip(ek, 32, 256, key_data, key_data_len);
WPA_PUT_BE16(key_mic + mic_len, key_data_len);
-#endif /* CONFIG_NO_RC4 */
+#endif /* !(CONFIG_NO_RC4 || CONFIG_FIPS) */
} else {
os_free(hdr);
- os_free(buf);
+ bin_clear_free(buf, key_data_len);
return;
}
- os_free(buf);
+ bin_clear_free(buf, key_data_len);
}
if (key_info & WPA_KEY_INFO_MIC) {
if (!sm->PTK_valid || !mic_len) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_DEBUG,
"PTK not valid when sending EAPOL-Key frame");
os_free(hdr);
return;
@@ -1691,7 +1763,8 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
if (!pairwise &&
conf->corrupt_gtk_rekey_mic_probability > 0.0 &&
drand48() < conf->corrupt_gtk_rekey_mic_probability) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_INFO,
"Corrupting group EAPOL-Key Key MIC");
key_mic[0]++;
}
@@ -1699,6 +1772,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
}
wpa_auth_set_eapol(wpa_auth, sm->addr, WPA_EAPOL_inc_EapolFramesTx, 1);
+ wpa_hexdump(MSG_DEBUG, "Send EAPOL-Key msg", hdr, len);
wpa_auth_send_eapol(wpa_auth, sm->addr, (u8 *) hdr, len,
sm->pairwise_set);
os_free(hdr);
@@ -1718,10 +1792,25 @@ static void wpa_send_eapol(struct wpa_authenticator *wpa_auth,
if (!sm)
return;
+ ctr = pairwise ? sm->TimeoutCtr : sm->GTimeoutCtr;
+
+#ifdef CONFIG_TESTING_OPTIONS
+ /* When delay_eapol_tx is true, delay the EAPOL-Key transmission by
+ * sending it only on the last attempt after all timeouts for the prior
+ * skipped attemps. */
+ if (wpa_auth->conf.delay_eapol_tx &&
+ ctr != wpa_auth->conf.wpa_pairwise_update_count) {
+ wpa_msg(sm->wpa_auth->conf.msg_ctx, MSG_INFO,
+ "DELAY-EAPOL-TX-%d", ctr);
+ goto skip_tx;
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
__wpa_send_eapol(wpa_auth, sm, key_info, key_rsc, nonce, kde, kde_len,
keyidx, encr, 0);
+#ifdef CONFIG_TESTING_OPTIONS
+skip_tx:
+#endif /* CONFIG_TESTING_OPTIONS */
- ctr = pairwise ? sm->TimeoutCtr : sm->GTimeoutCtr;
if (ctr == 1 && wpa_auth->conf.tx_status)
timeout_ms = pairwise ? eapol_key_timeout_first :
eapol_key_timeout_first_group;
@@ -1805,7 +1894,7 @@ int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event)
if (!sm)
return -1;
- wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_vlogger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
"event %d notification", event);
switch (event) {
@@ -1823,9 +1912,9 @@ int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event)
case WPA_DEAUTH:
case WPA_DISASSOC:
sm->DeauthenticationRequest = true;
-#ifdef CONFIG_IEEE80211R_AP
os_memset(sm->PMK, 0, sizeof(sm->PMK));
sm->pmk_len = 0;
+#ifdef CONFIG_IEEE80211R_AP
os_memset(sm->xxkey, 0, sizeof(sm->xxkey));
sm->xxkey_len = 0;
os_memset(sm->pmk_r1, 0, sizeof(sm->pmk_r1));
@@ -1853,11 +1942,19 @@ int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event)
break;
}
+ if (sm->ptkstart_without_success > 3) {
+ wpa_printf(MSG_INFO,
+ "WPA: Multiple EAP reauth attempts without 4-way handshake completion, disconnect "
+ MACSTR, MAC2STR(sm->addr));
+ sm->Disconnect = true;
+ break;
+ }
+
if (!sm->use_ext_key_id &&
sm->wpa_auth->conf.wpa_deny_ptk0_rekey) {
wpa_printf(MSG_INFO,
"WPA: PTK0 rekey not allowed, disconnect "
- MACSTR, MAC2STR(sm->addr));
+ MACSTR, MAC2STR(wpa_auth_get_spa(sm)));
sm->Disconnect = true;
/* Try to encourage the STA to reconnect */
sm->disconnect_reason =
@@ -2104,7 +2201,8 @@ SM_STATE(WPA_PTK, INITPMK)
sm->disconnect_reason = WLAN_REASON_INVALID_PMKID;
return;
#endif /* CONFIG_DPP */
- } else if (wpa_auth_get_msk(sm->wpa_auth, sm->addr, msk, &len) == 0) {
+ } else if (wpa_auth_get_msk(sm->wpa_auth, wpa_auth_get_spa(sm),
+ msk, &len) == 0) {
unsigned int pmk_len;
if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt))
@@ -2167,13 +2265,20 @@ SM_STATE(WPA_PTK, INITPSK)
os_memcpy(sm->PMK, psk, psk_len);
sm->pmk_len = psk_len;
#ifdef CONFIG_IEEE80211R_AP
- os_memcpy(sm->xxkey, psk, PMK_LEN);
sm->xxkey_len = PMK_LEN;
+#ifdef CONFIG_SAE
+ if (sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_SAE_EXT_KEY &&
+ (psk_len == SHA512_MAC_LEN || psk_len == SHA384_MAC_LEN ||
+ psk_len == SHA256_MAC_LEN))
+ sm->xxkey_len = psk_len;
+#endif /* CONFIG_SAE */
+ os_memcpy(sm->xxkey, psk, sm->xxkey_len);
#endif /* CONFIG_IEEE80211R_AP */
}
#ifdef CONFIG_SAE
if (wpa_auth_uses_sae(sm) && sm->pmksa) {
- wpa_printf(MSG_DEBUG, "SAE: PMK from PMKSA cache");
+ wpa_printf(MSG_DEBUG, "SAE: PMK from PMKSA cache (len=%zu)",
+ sm->pmksa->pmk_len);
os_memcpy(sm->PMK, sm->pmksa->pmk, sm->pmksa->pmk_len);
sm->pmk_len = sm->pmksa->pmk_len;
#ifdef CONFIG_IEEE80211R_AP
@@ -2190,11 +2295,13 @@ SM_STATE(WPA_PTK, PTKSTART)
{
u8 buf[2 + RSN_SELECTOR_LEN + PMKID_LEN], *pmkid = NULL;
size_t pmkid_len = 0;
+ u16 key_info;
SM_ENTRY_MA(WPA_PTK, PTKSTART, wpa_ptk);
sm->PTKRequest = false;
sm->TimeoutEvt = false;
sm->alt_snonce_valid = false;
+ sm->ptkstart_without_success++;
sm->TimeoutCtr++;
if (sm->TimeoutCtr > sm->wpa_auth->conf.wpa_pairwise_update_count) {
@@ -2203,7 +2310,7 @@ SM_STATE(WPA_PTK, PTKSTART)
return;
}
- wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
"sending 1/4 msg of 4-Way Handshake");
/*
* For infrastructure BSS cases, it is better for the AP not to include
@@ -2282,8 +2389,10 @@ SM_STATE(WPA_PTK, PTKSTART)
* Calculate PMKID since no PMKSA cache entry was
* available with pre-calculated PMKID.
*/
- rsn_pmkid(sm->PMK, sm->pmk_len, sm->wpa_auth->addr,
- sm->addr, &pmkid[2 + RSN_SELECTOR_LEN],
+ rsn_pmkid(sm->PMK, sm->pmk_len,
+ wpa_auth_get_aa(sm),
+ wpa_auth_get_spa(sm),
+ &pmkid[2 + RSN_SELECTOR_LEN],
sm->wpa_key_mgmt);
wpa_hexdump(MSG_DEBUG,
"RSN: Message 1/4 PMKID derived from PMK",
@@ -2292,19 +2401,24 @@ SM_STATE(WPA_PTK, PTKSTART)
}
if (!pmkid)
pmkid_len = 0;
- wpa_send_eapol(sm->wpa_auth, sm,
- WPA_KEY_INFO_ACK | WPA_KEY_INFO_KEY_TYPE, NULL,
+ key_info = WPA_KEY_INFO_ACK | WPA_KEY_INFO_KEY_TYPE;
+ if (sm->pairwise_set && sm->wpa != WPA_VERSION_WPA)
+ key_info |= WPA_KEY_INFO_SECURE;
+ wpa_send_eapol(sm->wpa_auth, sm, key_info, NULL,
sm->ANonce, pmkid, pmkid_len, 0, 0);
}
static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
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;
size_t z_len = 0, kdk_len;
int akmp;
+ int ret;
if (sm->wpa_auth->conf.force_kdk_derivation ||
(sm->wpa_auth->conf.secure_ltf &&
@@ -2318,16 +2432,36 @@ static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
if (sm->ft_completed) {
u8 ptk_name[WPA_PMK_NAME_LEN];
- return wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->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,
- kdk_len);
+ ret = wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->pmk_r1_len,
+ sm->SNonce, sm->ANonce,
+ wpa_auth_get_spa(sm),
+ wpa_auth_get_aa(sm),
+ sm->pmk_r1_name, ptk,
+ ptk_name, sm->wpa_key_mgmt,
+ sm->pairwise, kdk_len);
+ } else {
+ ret = wpa_auth_derive_ptk_ft(sm, ptk, pmk_r0, pmk_r1,
+ pmk_r0_name, key_len,
+ kdk_len);
+ }
+ if (ret) {
+ wpa_printf(MSG_ERROR, "FT: PTK derivation failed");
+ return ret;
}
- return wpa_auth_derive_ptk_ft(sm, ptk);
+
+#ifdef CONFIG_PASN
+ if (sm->wpa_auth->conf.secure_ltf &&
+ ieee802_11_rsnx_capab(sm->rsnxe,
+ WLAN_RSNX_CAPAB_SECURE_LTF)) {
+ ret = wpa_ltf_keyseed(ptk, sm->wpa_key_mgmt,
+ sm->pairwise);
+ if (ret) {
+ wpa_printf(MSG_ERROR,
+ "FT: LTF keyseed derivation failed");
+ }
+ }
+#endif /* CONFIG_PASN */
+ return ret;
}
#endif /* CONFIG_IEEE80211R_AP */
@@ -2341,9 +2475,27 @@ static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
akmp = sm->wpa_key_mgmt;
if (force_sha256)
akmp |= WPA_KEY_MGMT_PSK_SHA256;
- return wpa_pmk_to_ptk(pmk, pmk_len, "Pairwise key expansion",
- sm->wpa_auth->addr, sm->addr, sm->ANonce, snonce,
- ptk, akmp, sm->pairwise, z, z_len, kdk_len);
+ ret = wpa_pmk_to_ptk(pmk, pmk_len, "Pairwise key expansion",
+ wpa_auth_get_aa(sm), wpa_auth_get_spa(sm),
+ sm->ANonce, snonce, ptk, akmp,
+ sm->pairwise, z, z_len, kdk_len);
+ if (ret) {
+ wpa_printf(MSG_DEBUG,
+ "WPA: PTK derivation failed");
+ return ret;
+ }
+
+#ifdef CONFIG_PASN
+ if (sm->wpa_auth->conf.secure_ltf &&
+ ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)) {
+ ret = wpa_ltf_keyseed(ptk, sm->wpa_key_mgmt, sm->pairwise);
+ if (ret) {
+ wpa_printf(MSG_DEBUG,
+ "WPA: LTF keyseed derivation failed");
+ }
+ }
+#endif /* CONFIG_PASN */
+ return ret;
}
@@ -2367,13 +2519,27 @@ int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk,
else
kdk_len = 0;
- res = fils_pmk_to_ptk(pmk, pmk_len, sm->addr, sm->wpa_auth->addr,
+ res = fils_pmk_to_ptk(pmk, pmk_len, wpa_auth_get_spa(sm),
+ wpa_auth_get_aa(sm),
snonce, anonce, dhss, dhss_len,
&sm->PTK, ick, &ick_len,
sm->wpa_key_mgmt, sm->pairwise,
fils_ft, &fils_ft_len, kdk_len);
if (res < 0)
return res;
+
+#ifdef CONFIG_PASN
+ if (sm->wpa_auth->conf.secure_ltf &&
+ ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)) {
+ res = wpa_ltf_keyseed(&sm->PTK, sm->wpa_key_mgmt, sm->pairwise);
+ if (res) {
+ wpa_printf(MSG_ERROR,
+ "FILS: LTF keyseed derivation failed");
+ return res;
+ }
+ }
+#endif /* CONFIG_PASN */
+
sm->PTK_valid = true;
sm->tk_already_set = false;
@@ -2382,23 +2548,23 @@ int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk,
struct wpa_authenticator *wpa_auth = sm->wpa_auth;
struct wpa_auth_config *conf = &wpa_auth->conf;
u8 pmk_r0[PMK_LEN_MAX], pmk_r0_name[WPA_PMK_NAME_LEN];
- int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt);
if (wpa_derive_pmk_r0(fils_ft, fils_ft_len,
conf->ssid, conf->ssid_len,
conf->mobility_domain,
conf->r0_key_holder,
conf->r0_key_holder_len,
- sm->addr, pmk_r0, pmk_r0_name,
- use_sha384) < 0)
+ wpa_auth_get_spa(sm), pmk_r0, pmk_r0_name,
+ sm->wpa_key_mgmt) < 0)
return -1;
wpa_ft_store_pmk_fils(sm, pmk_r0, pmk_r0_name);
forced_memzero(fils_ft, sizeof(fils_ft));
res = wpa_derive_pmk_r1_name(pmk_r0_name, conf->r1_key_holder,
- sm->addr, sm->pmk_r1_name,
- use_sha384);
+ wpa_auth_get_spa(sm),
+ sm->pmk_r1_name,
+ fils_ft_len);
forced_memzero(pmk_r0, PMK_LEN_MAX);
if (res < 0)
return -1;
@@ -2409,7 +2575,8 @@ int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk,
#endif /* CONFIG_IEEE80211R_AP */
res = fils_key_auth_sk(ick, ick_len, snonce, anonce,
- sm->addr, sm->wpa_auth->addr,
+ wpa_auth_get_spa(sm),
+ wpa_auth_get_aa(sm),
g_sta ? wpabuf_head(g_sta) : NULL,
g_sta ? wpabuf_len(g_sta) : 0,
g_ap ? wpabuf_head(g_ap) : NULL,
@@ -2444,7 +2611,7 @@ static int wpa_aead_decrypt(struct wpa_state_machine *sm, struct wpa_ptk *ptk,
key_data_len = WPA_GET_BE16(pos);
if (key_data_len < AES_BLOCK_SIZE ||
key_data_len > buf_len - sizeof(*hdr) - sizeof(*key) - 2) {
- wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
"No room for AES-SIV data in the frame");
return -1;
}
@@ -2460,7 +2627,7 @@ static int wpa_aead_decrypt(struct wpa_state_machine *sm, struct wpa_ptk *ptk,
aad_len[0] = pos - buf;
if (aes_siv_decrypt(ptk->kek, ptk->kek_len, pos, key_data_len,
1, aad, aad_len, tmp) < 0) {
- wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
"Invalid AES-SIV data in the frame");
bin_clear_free(tmp, key_data_len);
return -1;
@@ -2877,6 +3044,20 @@ int fils_set_tk(struct wpa_state_machine *sm)
wpa_printf(MSG_DEBUG, "FILS: Failed to set TK to the driver");
return -1;
}
+
+#ifdef CONFIG_PASN
+ if (sm->wpa_auth->conf.secure_ltf &&
+ ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF) &&
+ wpa_auth_set_ltf_keyseed(sm->wpa_auth, sm->addr,
+ sm->PTK.ltf_keyseed,
+ sm->PTK.ltf_keyseed_len)) {
+ wpa_printf(MSG_ERROR,
+ "FILS: Failed to set LTF keyseed to driver");
+ return -1;
+ }
+#endif /* CONFIG_PASN */
+
+ sm->pairwise_set = true;
sm->tk_already_set = true;
wpa_auth_store_ptksa(sm->wpa_auth, sm->addr, sm->pairwise,
@@ -2949,6 +3130,9 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
struct wpa_eapol_ie_parse kde;
int vlan_id = 0;
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->EAPOLKeyReceived = false;
@@ -2987,7 +3171,8 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
}
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;
if (mic_len &&
@@ -3026,12 +3211,26 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
break;
}
+ if (!ok && wpa_key_mgmt_wpa_psk_no_sae(sm->wpa_key_mgmt) &&
+ wpa_auth->conf.radius_psk && wpa_auth->cb->request_radius_psk &&
+ !sm->waiting_radius_psk) {
+ wpa_printf(MSG_DEBUG, "No PSK available - ask RADIUS server");
+ wpa_auth->cb->request_radius_psk(wpa_auth->cb_ctx, sm->addr,
+ sm->wpa_key_mgmt,
+ sm->ANonce,
+ sm->last_rx_eapol_key,
+ sm->last_rx_eapol_key_len);
+ sm->waiting_radius_psk = 1;
+ goto out;
+ }
+
if (!ok) {
- wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_DEBUG,
"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;
}
/*
@@ -3045,12 +3244,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,
+ wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm), 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;
@@ -3066,7 +3265,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
if (!sm->wpa_ie ||
wpa_compare_rsn_ie(ft, sm->wpa_ie, sm->wpa_ie_len,
eapol_key_ie, eapol_key_ie_len)) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
"WPA IE from (Re)AssocReq did not match with msg 2/4");
if (sm->wpa_ie) {
wpa_hexdump(MSG_DEBUG, "WPA IE in AssocReq",
@@ -3077,14 +3276,14 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
/* MLME-DEAUTHENTICATE.request */
wpa_sta_disconnect(wpa_auth, sm->addr,
WLAN_REASON_PREV_AUTH_NOT_VALID);
- return;
+ goto out;
}
if ((!sm->rsnxe && kde.rsnxe) ||
(sm->rsnxe && !kde.rsnxe) ||
(sm->rsnxe && kde.rsnxe &&
(sm->rsnxe_len != kde.rsnxe_len ||
os_memcmp(sm->rsnxe, kde.rsnxe, sm->rsnxe_len) != 0))) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
"RSNXE from (Re)AssocReq did not match the one in EAPOL-Key msg 2/4");
wpa_hexdump(MSG_DEBUG, "RSNXE in AssocReq",
sm->rsnxe, sm->rsnxe_len);
@@ -3093,7 +3292,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)) {
@@ -3103,33 +3302,37 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
enum oci_verify_result res;
if (wpa_channel_info(wpa_auth, &ci) != 0) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
+ 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;
res = ocv_verify_tx_params(kde.oci, kde.oci_len, &ci,
tx_chanwidth, tx_seg1_idx);
if (wpa_auth_uses_ocv(sm) == 2 && res == OCI_NOT_FOUND) {
/* Work around misbehaving STAs */
- wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_INFO,
"Disable OCV with a STA that does not send OCI");
wpa_auth_set_ocv(sm, 0);
} else if (res != OCI_SUCCESS) {
- wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_INFO,
"OCV failed: %s", ocv_errorstr);
if (wpa_auth->conf.msg_ctx)
wpa_msg(wpa_auth->conf.msg_ctx, MSG_INFO,
OCV_FAILURE "addr=" MACSTR
" frame=eapol-key-m2 error=%s",
- MAC2STR(sm->addr), ocv_errorstr);
- return;
+ MAC2STR(wpa_auth_get_spa(sm)),
+ ocv_errorstr);
+ goto out;
}
}
#endif /* CONFIG_OCV */
@@ -3137,7 +3340,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
@@ -3150,12 +3353,15 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
if (idx >= 0) {
u32 start = WPA_GET_BE32(wpa_auth->conf.ip_addr_start);
bitfield_set(wpa_auth->ip_pool, idx);
+ sm->ip_addr_bit = idx;
WPA_PUT_BE32(sm->ip_addr, start + idx);
wpa_printf(MSG_DEBUG,
"P2P: Assigned IP address %u.%u.%u.%u to "
- MACSTR, sm->ip_addr[0], sm->ip_addr[1],
+ MACSTR " (bit %u)",
+ sm->ip_addr[0], sm->ip_addr[1],
sm->ip_addr[2], sm->ip_addr[3],
- MAC2STR(sm->addr));
+ MAC2STR(wpa_auth_get_spa(sm)),
+ sm->ip_addr_bit);
}
}
#endif /* CONFIG_P2P */
@@ -3173,7 +3379,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");
wpa_sta_disconnect(wpa_auth, sm->addr,
WLAN_REASON_PREV_AUTH_NOT_VALID);
- return;
+ goto out;
}
}
#endif /* CONFIG_DPP2 */
@@ -3186,14 +3392,15 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
*/
if (os_memcmp_const(sm->sup_pmk_r1_name, sm->pmk_r1_name,
WPA_PMK_NAME_LEN) != 0) {
- wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_DEBUG,
"PMKR1Name mismatch in FT 4-way handshake");
wpa_hexdump(MSG_DEBUG,
"FT: PMKR1Name from Supplicant",
sm->sup_pmk_r1_name, WPA_PMK_NAME_LEN);
wpa_hexdump(MSG_DEBUG, "FT: Derived PMKR1Name",
sm->pmk_r1_name, WPA_PMK_NAME_LEN);
- return;
+ goto out;
}
}
#endif /* CONFIG_IEEE80211R_AP */
@@ -3202,7 +3409,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;
@@ -3218,9 +3425,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));
}
@@ -3279,6 +3497,7 @@ static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos)
pos = wpa_add_kde(pos, RSN_KEY_DATA_IGTK,
(const u8 *) &igtk, WPA_IGTK_KDE_PREFIX_LEN + len,
NULL, 0);
+ forced_memzero(&igtk, sizeof(igtk));
if (!conf->beacon_prot)
return pos;
@@ -3302,6 +3521,7 @@ static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos)
pos = wpa_add_kde(pos, RSN_KEY_DATA_BIGTK,
(const u8 *) &bigtk, WPA_BIGTK_KDE_PREFIX_LEN + len,
NULL, 0);
+ forced_memzero(&bigtk, sizeof(bigtk));
return pos;
}
@@ -3382,7 +3602,7 @@ static u8 * replace_ie(const char *name, const u8 *old_buf, size_t *len, u8 eid,
SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
{
u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde = NULL, *pos, stub_gtk[32];
- size_t gtk_len, kde_len, wpa_ie_len;
+ size_t gtk_len, kde_len = 0, wpa_ie_len;
struct wpa_group *gsm = sm->group;
u8 *wpa_ie;
int secure, gtkidx, encr = 0;
@@ -3442,7 +3662,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
wpa_ie = wpa_ie_buf;
}
#endif /* CONFIG_TESTING_OPTIONS */
- wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
"sending 3/4 msg of 4-Way Handshake");
if (sm->wpa == WPA_VERSION_WPA2) {
if (sm->use_ext_key_id && sm->TimeoutCtr == 1 &&
@@ -3457,6 +3677,21 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
return;
}
+#ifdef CONFIG_PASN
+ if (sm->wpa_auth->conf.secure_ltf &&
+ ieee802_11_rsnx_capab(sm->rsnxe,
+ WLAN_RSNX_CAPAB_SECURE_LTF) &&
+ wpa_auth_set_ltf_keyseed(sm->wpa_auth, sm->addr,
+ sm->PTK.ltf_keyseed,
+ sm->PTK.ltf_keyseed_len)) {
+ wpa_printf(MSG_ERROR,
+ "WPA: Failed to set LTF keyseed to driver");
+ wpa_sta_disconnect(sm->wpa_auth, sm->addr,
+ WLAN_REASON_PREV_AUTH_NOT_VALID);
+ return;
+ }
+#endif /* CONFIG_PASN */
+
/* WPA2 send GTK in the 4-way handshake */
secure = 1;
gtk = gsm->GTK[gsm->GN - 1];
@@ -3489,7 +3724,8 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
* by setting the Secure bit here even in the case of
* WPA if the supplicant used it first.
*/
- wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_DEBUG,
"STA used Secure bit in WPA msg 2/4 - set Secure for 3/4 as workaround");
secure = 1;
}
@@ -3570,9 +3806,8 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
2 + sm->assoc_resp_ftie[1]);
res = 2 + sm->assoc_resp_ftie[1];
} else {
- int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt);
-
- res = wpa_write_ftie(conf, use_sha384,
+ res = wpa_write_ftie(conf, sm->wpa_key_mgmt,
+ sm->xxkey_len,
conf->r0_key_holder,
conf->r0_key_holder_len,
NULL, NULL, pos,
@@ -3640,7 +3875,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
WPA_KEY_INFO_KEY_TYPE,
_rsc, sm->ANonce, kde, pos - kde, 0, encr);
done:
- os_free(kde);
+ bin_clear_free(kde, kde_len);
os_free(wpa_ie_buf);
os_free(wpa_ie_buf2);
}
@@ -3668,6 +3903,22 @@ SM_STATE(WPA_PTK, PTKINITDONE)
WLAN_REASON_PREV_AUTH_NOT_VALID);
return;
}
+
+#ifdef CONFIG_PASN
+ if (sm->wpa_auth->conf.secure_ltf &&
+ ieee802_11_rsnx_capab(sm->rsnxe,
+ WLAN_RSNX_CAPAB_SECURE_LTF) &&
+ wpa_auth_set_ltf_keyseed(sm->wpa_auth, sm->addr,
+ sm->PTK.ltf_keyseed,
+ sm->PTK.ltf_keyseed_len)) {
+ wpa_printf(MSG_ERROR,
+ "WPA: Failed to set LTF keyseed to driver");
+ wpa_sta_disconnect(sm->wpa_auth, sm->addr,
+ WLAN_REASON_PREV_AUTH_NOT_VALID);
+ return;
+ }
+#endif /* CONFIG_PASN */
+
/* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */
sm->pairwise_set = true;
@@ -3700,15 +3951,17 @@ SM_STATE(WPA_PTK, PTKINITDONE)
sm->PInitAKeys = true;
else
sm->has_GTK = true;
- wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_vlogger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
"pairwise key handshake completed (%s)",
sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN");
wpa_msg(sm->wpa_auth->conf.msg_ctx, MSG_INFO, "EAPOL-4WAY-HS-COMPLETED "
MACSTR, MAC2STR(sm->addr));
#ifdef CONFIG_IEEE80211R_AP
- wpa_ft_push_pmk_r1(sm->wpa_auth, sm->addr);
+ wpa_ft_push_pmk_r1(sm->wpa_auth, wpa_auth_get_spa(sm));
#endif /* CONFIG_IEEE80211R_AP */
+
+ sm->ptkstart_without_success = 0;
}
@@ -3721,7 +3974,7 @@ SM_STEP(WPA_PTK)
SM_ENTER(WPA_PTK, INITIALIZE);
else if (sm->Disconnect
/* || FIX: dot11RSNAConfigSALifetime timeout */) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
"WPA_PTK: sm->Disconnect");
SM_ENTER(WPA_PTK, DISCONNECT);
}
@@ -3770,7 +4023,8 @@ SM_STEP(WPA_PTK)
#endif /* CONFIG_DPP */
} else {
wpa_auth->dot11RSNA4WayHandshakeFailures++;
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_INFO,
"INITPMK - keyAvailable = false");
SM_ENTER(WPA_PTK, DISCONNECT);
}
@@ -3783,8 +4037,14 @@ SM_STEP(WPA_PTK)
} else if (wpa_auth_uses_sae(sm) && sm->pmksa) {
SM_ENTER(WPA_PTK, PTKSTART);
#endif /* CONFIG_SAE */
+ } else if (wpa_key_mgmt_wpa_psk_no_sae(sm->wpa_key_mgmt) &&
+ wpa_auth->conf.radius_psk) {
+ wpa_printf(MSG_DEBUG,
+ "INITPSK: No PSK yet available for STA - use RADIUS later");
+ SM_ENTER(WPA_PTK, PTKSTART);
} else {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_INFO,
"no PSK configured for the STA");
wpa_auth->dot11RSNA4WayHandshakeFailures++;
SM_ENTER(WPA_PTK, DISCONNECT);
@@ -3796,7 +4056,8 @@ SM_STEP(WPA_PTK)
SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING);
else if (sm->TimeoutCtr > conf->wpa_pairwise_update_count) {
wpa_auth->dot11RSNA4WayHandshakeFailures++;
- wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_DEBUG,
"PTKSTART: Retry limit %u reached",
conf->wpa_pairwise_update_count);
sm->disconnect_reason =
@@ -3828,7 +4089,8 @@ SM_STEP(WPA_PTK)
(conf->wpa_disable_eapol_key_retries &&
sm->TimeoutCtr > 1)) {
wpa_auth->dot11RSNA4WayHandshakeFailures++;
- wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_DEBUG,
"PTKINITNEGOTIATING: Retry limit %u reached",
conf->wpa_pairwise_update_count);
sm->disconnect_reason =
@@ -3861,7 +4123,7 @@ SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING)
struct wpa_group *gsm = sm->group;
const u8 *kde;
u8 *kde_buf = NULL, *pos, hdr[2];
- size_t kde_len;
+ size_t kde_len = 0;
u8 *gtk, stub_gtk[32];
struct wpa_auth_config *conf = &sm->wpa_auth->conf;
@@ -3885,7 +4147,7 @@ SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING)
os_memset(rsc, 0, WPA_KEY_RSC_LEN);
if (gsm->wpa_group_state == WPA_GROUP_SETKEYSDONE)
wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc);
- wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
"sending 1/2 msg of Group Key Handshake");
gtk = gsm->GTK[gsm->GN - 1];
@@ -3930,7 +4192,7 @@ SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING)
(!sm->Pair ? WPA_KEY_INFO_INSTALL : 0),
rsc, NULL, kde, kde_len, gsm->GN, 1);
- os_free(kde_buf);
+ bin_clear_free(kde_buf, kde_len);
}
@@ -3966,7 +4228,7 @@ SM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED)
return;
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, wpa_auth_get_spa(sm), LOGGER_INFO,
"received EAPOL-Key group msg 2/2 with invalid Key Data contents");
return;
}
@@ -3977,7 +4239,8 @@ SM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED)
int tx_seg1_idx;
if (wpa_channel_info(wpa_auth, &ci) != 0) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_INFO,
"Failed to get channel info to validate received OCI in EAPOL-Key group 2/2");
return;
}
@@ -3991,13 +4254,15 @@ SM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED)
if (ocv_verify_tx_params(kde.oci, kde.oci_len, &ci,
tx_chanwidth, tx_seg1_idx) !=
OCI_SUCCESS) {
- wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_INFO,
"OCV failed: %s", ocv_errorstr);
if (wpa_auth->conf.msg_ctx)
wpa_msg(wpa_auth->conf.msg_ctx, MSG_INFO,
OCV_FAILURE "addr=" MACSTR
" frame=eapol-key-g2 error=%s",
- MAC2STR(sm->addr), ocv_errorstr);
+ MAC2STR(wpa_auth_get_spa(sm)),
+ ocv_errorstr);
return;
}
}
@@ -4008,7 +4273,7 @@ SM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED)
sm->GUpdateStationKeys = false;
sm->GTimeoutCtr = 0;
/* FIX: MLME.SetProtection.Request(TA, Tx_Rx) */
- wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
"group key handshake completed (%s)",
sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN");
sm->has_GTK = true;
@@ -4023,7 +4288,7 @@ SM_STATE(WPA_PTK_GROUP, KEYERROR)
sm->GUpdateStationKeys = false;
sm->Disconnect = true;
sm->disconnect_reason = WLAN_REASON_GROUP_KEY_UPDATE_TIMEOUT;
- wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_vlogger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
"group key handshake failed (%s) after %u tries",
sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN",
sm->wpa_auth->conf.wpa_group_update_count);
@@ -4136,7 +4401,8 @@ static int wpa_group_update_sta(struct wpa_state_machine *sm, void *ctx)
return 0;
if (sm->wpa_ptk_state != WPA_PTK_PTKINITDONE) {
- wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_DEBUG,
"Not in PTKINITDONE; skip Group Key update");
sm->GUpdateStationKeys = false;
return 0;
@@ -4147,7 +4413,8 @@ static int wpa_group_update_sta(struct wpa_state_machine *sm, void *ctx)
* Since we clear the GKeyDoneStations before the loop, the
* station needs to be counted here anyway.
*/
- wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_DEBUG,
"GUpdateStationKeys was already set when marking station for GTK rekeying");
}
@@ -4381,7 +4648,7 @@ static int wpa_group_disconnect_cb(struct wpa_state_machine *sm, void *ctx)
if (sm->group == ctx) {
wpa_printf(MSG_DEBUG, "WPA: Mark STA " MACSTR
" for disconnection due to fatal failure",
- MAC2STR(sm->addr));
+ MAC2STR(wpa_auth_get_spa(sm)));
sm->Disconnect = true;
}
@@ -4474,7 +4741,7 @@ static int wpa_sm_step(struct wpa_state_machine *sm)
if (sm->pending_deinit) {
wpa_printf(MSG_DEBUG,
"WPA: Completing pending STA state machine deinit for "
- MACSTR, MAC2STR(sm->addr));
+ MACSTR, MAC2STR(wpa_auth_get_spa(sm)));
wpa_free_sta_sm(sm);
return 1;
}
@@ -4667,11 +4934,13 @@ int wpa_get_mib_sta(struct wpa_state_machine *sm, char *buf, size_t buflen)
"wpa=%d\n"
"AKMSuiteSelector=" RSN_SUITE "\n"
"hostapdWPAPTKState=%d\n"
- "hostapdWPAPTKGroupState=%d\n",
+ "hostapdWPAPTKGroupState=%d\n"
+ "hostapdMFPR=%d\n",
sm->wpa,
RSN_SUITE_ARG(wpa_akm_to_suite(sm->wpa_key_mgmt)),
sm->wpa_ptk_state,
- sm->wpa_ptk_group_state);
+ sm->wpa_ptk_group_state,
+ sm->mfpr);
if (os_snprintf_error(buflen - len, ret))
return len;
len += ret;
@@ -4708,6 +4977,14 @@ const u8 * wpa_auth_get_pmk(struct wpa_state_machine *sm, int *len)
}
+const u8 * wpa_auth_get_dpp_pkhash(struct wpa_state_machine *sm)
+{
+ if (!sm || !sm->pmksa)
+ return NULL;
+ return sm->pmksa->dpp_pkhash;
+}
+
+
int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm)
{
if (!sm)
@@ -4800,7 +5077,8 @@ int wpa_auth_pmksa_add(struct wpa_state_machine *sm, const u8 *pmk,
wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK", pmk, pmk_len);
if (pmksa_cache_auth_add(sm->wpa_auth->pmksa, pmk, pmk_len, NULL,
sm->PTK.kck, sm->PTK.kck_len,
- sm->wpa_auth->addr, sm->addr, session_timeout,
+ wpa_auth_get_aa(sm),
+ wpa_auth_get_spa(sm), session_timeout,
eapol, sm->wpa_key_mgmt))
return 0;
@@ -4829,16 +5107,17 @@ int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth,
int wpa_auth_pmksa_add_sae(struct wpa_authenticator *wpa_auth, const u8 *addr,
- const u8 *pmk, const u8 *pmkid)
+ const u8 *pmk, size_t pmk_len, const u8 *pmkid,
+ int akmp)
{
if (wpa_auth->conf.disable_pmksa_caching)
return -1;
- wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK from SAE", pmk, PMK_LEN);
- if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, PMK_LEN, pmkid,
- NULL, 0,
- wpa_auth->addr, addr, 0, NULL,
- WPA_KEY_MGMT_SAE))
+ wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK from SAE", pmk, pmk_len);
+ if (!akmp)
+ akmp = WPA_KEY_MGMT_SAE;
+ if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, pmk_len, pmkid,
+ NULL, 0, wpa_auth->addr, addr, 0, NULL, akmp))
return 0;
return -1;
@@ -4869,6 +5148,29 @@ int wpa_auth_pmksa_add2(struct wpa_authenticator *wpa_auth, const u8 *addr,
}
+int wpa_auth_pmksa_add3(struct wpa_authenticator *wpa_auth, const u8 *addr,
+ const u8 *pmk, size_t pmk_len, const u8 *pmkid,
+ int session_timeout, int akmp, const u8 *dpp_pkhash)
+{
+ struct rsn_pmksa_cache_entry *entry;
+
+ if (wpa_auth->conf.disable_pmksa_caching)
+ return -1;
+
+ wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK (3)", pmk, PMK_LEN);
+ entry = pmksa_cache_auth_add(wpa_auth->pmksa, pmk, pmk_len, pmkid,
+ NULL, 0, wpa_auth->addr, addr, session_timeout,
+ NULL, akmp);
+ if (!entry)
+ return -1;
+
+ if (dpp_pkhash)
+ entry->dpp_pkhash = os_memdup(dpp_pkhash, SHA256_MAC_LEN);
+
+ return 0;
+}
+
+
void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth,
const u8 *sta_addr)
{
@@ -4916,13 +5218,14 @@ int wpa_auth_pmksa_list_mesh(struct wpa_authenticator *wpa_auth, const u8 *addr,
struct rsn_pmksa_cache_entry *
wpa_auth_pmksa_create_entry(const u8 *aa, const u8 *spa, const u8 *pmk,
+ size_t pmk_len, int akmp,
const u8 *pmkid, int expiration)
{
struct rsn_pmksa_cache_entry *entry;
struct os_reltime now;
- entry = pmksa_cache_auth_create_entry(pmk, PMK_LEN, pmkid, NULL, 0, aa,
- spa, 0, NULL, WPA_KEY_MGMT_SAE);
+ entry = pmksa_cache_auth_create_entry(pmk, pmk_len, pmkid, NULL, 0, aa,
+ spa, 0, NULL, akmp);
if (!entry)
return NULL;
@@ -4953,6 +5256,15 @@ int wpa_auth_pmksa_add_entry(struct wpa_authenticator *wpa_auth,
#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
+struct rsn_pmksa_cache *
+wpa_auth_get_pmksa_cache(struct wpa_authenticator *wpa_auth)
+{
+ if (!wpa_auth || !wpa_auth->pmksa)
+ return NULL;
+ return wpa_auth->pmksa;
+}
+
+
struct rsn_pmksa_cache_entry *
wpa_auth_pmksa_get(struct wpa_authenticator *wpa_auth, const u8 *sta_addr,
const u8 *pmkid)
@@ -5176,7 +5488,7 @@ int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id)
wpa_printf(MSG_DEBUG, "WPA: Moving STA " MACSTR
" to use group state machine for VLAN ID %d",
- MAC2STR(sm->addr), vlan_id);
+ MAC2STR(wpa_auth_get_spa(sm)), vlan_id);
wpa_group_get(sm->wpa_auth, group);
wpa_group_put(sm->wpa_auth, sm->group);
@@ -5192,7 +5504,7 @@ void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth,
if (!wpa_auth || !sm)
return;
wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key TX status for STA " MACSTR
- " ack=%d", MAC2STR(sm->addr), ack);
+ " ack=%d", MAC2STR(wpa_auth_get_spa(sm)), ack);
if (sm->pending_1_of_4_timeout && ack) {
/*
* Some deployed supplicant implementations update their SNonce
@@ -5236,7 +5548,8 @@ int wpa_auth_uses_ft_sae(struct wpa_state_machine *sm)
{
if (!sm)
return 0;
- return sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_SAE;
+ return sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_SAE ||
+ sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_SAE_EXT_KEY;
}
@@ -5312,13 +5625,14 @@ wpa_auth_pmksa_get_fils_cache_id(struct wpa_authenticator *wpa_auth,
#ifdef CONFIG_IEEE80211R_AP
-int wpa_auth_write_fte(struct wpa_authenticator *wpa_auth, int use_sha384,
+int wpa_auth_write_fte(struct wpa_authenticator *wpa_auth,
+ struct wpa_state_machine *sm,
u8 *buf, size_t len)
{
struct wpa_auth_config *conf = &wpa_auth->conf;
- return wpa_write_ftie(conf, use_sha384, conf->r0_key_holder,
- conf->r0_key_holder_len,
+ return wpa_write_ftie(conf, sm->wpa_key_mgmt, sm->xxkey_len,
+ conf->r0_key_holder, conf->r0_key_holder_len,
NULL, NULL, buf, len, NULL, 0, 0);
}
#endif /* CONFIG_IEEE80211R_AP */
@@ -5388,7 +5702,7 @@ int wpa_auth_resend_m1(struct wpa_state_machine *sm, int change_anonce,
anonce = anonce_buf;
}
- wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
"sending 1/4 msg of 4-Way Handshake (TESTING)");
wpa_send_eapol(sm->wpa_auth, sm,
WPA_KEY_INFO_ACK | WPA_KEY_INFO_KEY_TYPE, NULL,
@@ -5430,7 +5744,7 @@ int wpa_auth_resend_m3(struct wpa_state_machine *sm,
wpa_ie = wpa_ie + wpa_ie[1] + 2;
wpa_ie_len = wpa_ie[1] + 2;
}
- wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
"sending 3/4 msg of 4-Way Handshake (TESTING)");
if (sm->wpa == WPA_VERSION_WPA2) {
/* WPA2 send GTK in the 4-way handshake */
@@ -5455,7 +5769,8 @@ int wpa_auth_resend_m3(struct wpa_state_machine *sm,
* by setting the Secure bit here even in the case of
* WPA if the supplicant used it first.
*/
- wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_DEBUG,
"STA used Secure bit in WPA msg 2/4 - set Secure for 3/4 as workaround");
secure = 1;
}
@@ -5532,9 +5847,8 @@ int wpa_auth_resend_m3(struct wpa_state_machine *sm,
2 + sm->assoc_resp_ftie[1]);
res = 2 + sm->assoc_resp_ftie[1];
} else {
- int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt);
-
- res = wpa_write_ftie(conf, use_sha384,
+ res = wpa_write_ftie(conf, sm->wpa_key_mgmt,
+ sm->xxkey_len,
conf->r0_key_holder,
conf->r0_key_holder_len,
NULL, NULL, pos,
@@ -5572,7 +5886,7 @@ int wpa_auth_resend_m3(struct wpa_state_machine *sm,
WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL |
WPA_KEY_INFO_KEY_TYPE,
_rsc, sm->ANonce, kde, pos - kde, 0, encr);
- os_free(kde);
+ bin_clear_free(kde, kde_len);
return 0;
}
@@ -5593,7 +5907,7 @@ int wpa_auth_resend_group_m1(struct wpa_state_machine *sm,
/* Send EAPOL(1, 1, 1, !Pair, G, RSC, GNonce, MIC(PTK), GTK[GN]) */
os_memset(rsc, 0, WPA_KEY_RSC_LEN);
/* Use 0 RSC */
- wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
"sending 1/2 msg of Group Key Handshake (TESTING)");
gtk = gsm->GTK[gsm->GN - 1];
@@ -5640,7 +5954,7 @@ int wpa_auth_resend_group_m1(struct wpa_state_machine *sm,
(!sm->Pair ? WPA_KEY_INFO_INSTALL : 0),
rsc, NULL, kde, kde_len, gsm->GN, 1);
- os_free(kde_buf);
+ bin_clear_free(kde_buf, kde_len);
return 0;
}
@@ -5711,3 +6025,28 @@ void wpa_auth_set_enable_eapol_large_timeout(struct wpa_authenticator *wpa_auth,
#endif /* CONFIG_TESTING_OPTIONS */
+
+
+void wpa_auth_sta_radius_psk_resp(struct wpa_state_machine *sm, bool success)
+{
+ if (!sm->waiting_radius_psk) {
+ wpa_printf(MSG_DEBUG,
+ "Ignore RADIUS PSK response for " MACSTR
+ " that did not wait one",
+ MAC2STR(sm->addr));
+ return;
+ }
+
+ wpa_printf(MSG_DEBUG, "RADIUS PSK response for " MACSTR " (%s)",
+ MAC2STR(sm->addr), success ? "success" : "fail");
+ sm->waiting_radius_psk = 0;
+
+ if (success) {
+ /* Try to process the EAPOL-Key msg 2/4 again */
+ sm->EAPOLKeyReceived = true;
+ } else {
+ sm->Disconnect = true;
+ }
+
+ eloop_register_timeout(0, 0, wpa_sm_call_step, sm, NULL);
+}