SAE: Fix PMKID in EAPOL-Key msg 1/4

Previously, the association that used SAE authentication ended up
recalculating the PMKID for EAPOL-Key msg 1/4 using incorrect
PMK-to-PMKID derivation instead of using the previously derived PMKID
from SAE. The correct PMKID was used only when going through PMKSA
caching exchange with a previously derived PMKSA from SAE.

Fix this by storing the SAE PMKID into the state machine entry for the
initial SAE authentication case when there is no explicit PMKSA entry
attached to the station.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
This commit is contained in:
Jouni Malinen 2018-03-23 17:45:44 +02:00 committed by Jouni Malinen
parent a03f9d17ea
commit 9d94e4bb6b
4 changed files with 37 additions and 0 deletions

View file

@ -2538,6 +2538,10 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
#endif /* CONFIG_IEEE80211R_AP */
#ifdef CONFIG_SAE
if (wpa_auth_uses_sae(sta->wpa_sm) && sta->sae &&
sta->sae->state == SAE_ACCEPTED)
wpa_auth_add_sae_pmkid(sta->wpa_sm, sta->sae->pmkid);
if (wpa_auth_uses_sae(sta->wpa_sm) &&
sta->auth_alg == WLAN_AUTH_OPEN) {
struct rsn_pmksa_cache_entry *sa;

View file

@ -2035,11 +2035,31 @@ SM_STATE(WPA_PTK, PTKSTART)
pmkid[1] = RSN_SELECTOR_LEN + PMKID_LEN;
RSN_SELECTOR_PUT(&pmkid[2], RSN_KEY_DATA_PMKID);
if (sm->pmksa) {
wpa_hexdump(MSG_DEBUG,
"RSN: Message 1/4 PMKID from PMKSA entry",
sm->pmksa->pmkid, PMKID_LEN);
os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN],
sm->pmksa->pmkid, PMKID_LEN);
} else if (wpa_key_mgmt_suite_b(sm->wpa_key_mgmt)) {
/* No KCK available to derive PMKID */
wpa_printf(MSG_DEBUG,
"RSN: No KCK available to derive PMKID for message 1/4");
pmkid = NULL;
#ifdef CONFIG_SAE
} else if (wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
if (sm->pmkid_set) {
wpa_hexdump(MSG_DEBUG,
"RSN: Message 1/4 PMKID from SAE",
sm->pmkid, PMKID_LEN);
os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN],
sm->pmkid, PMKID_LEN);
} else {
/* No PMKID available */
wpa_printf(MSG_DEBUG,
"RSN: No SAE PMKID available for message 1/4");
pmkid = NULL;
}
#endif /* CONFIG_SAE */
} else {
/*
* Calculate PMKID since no PMKSA cache entry was
@ -2048,6 +2068,9 @@ SM_STATE(WPA_PTK, PTKSTART)
rsn_pmkid(sm->PMK, sm->pmk_len, sm->wpa_auth->addr,
sm->addr, &pmkid[2 + RSN_SELECTOR_LEN],
sm->wpa_key_mgmt);
wpa_hexdump(MSG_DEBUG,
"RSN: Message 1/4 PMKID derived from PMK",
&pmkid[2 + RSN_SELECTOR_LEN], PMKID_LEN);
}
}
wpa_send_eapol(sm->wpa_auth, sm,
@ -4040,6 +4063,13 @@ int wpa_auth_pmksa_add_sae(struct wpa_authenticator *wpa_auth, const u8 *addr,
}
void wpa_auth_add_sae_pmkid(struct wpa_state_machine *sm, const u8 *pmkid)
{
os_memcpy(sm->pmkid, pmkid, PMKID_LEN);
sm->pmkid_set = 1;
}
int wpa_auth_pmksa_add2(struct wpa_authenticator *wpa_auth, const u8 *addr,
const u8 *pmk, size_t pmk_len, const u8 *pmkid,
int session_timeout, int akmp)

View file

@ -332,6 +332,7 @@ int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth,
struct eapol_state_machine *eapol);
int wpa_auth_pmksa_add_sae(struct wpa_authenticator *wpa_auth, const u8 *addr,
const u8 *pmk, const u8 *pmkid);
void wpa_auth_add_sae_pmkid(struct wpa_state_machine *sm, const u8 *pmkid);
int wpa_auth_pmksa_add2(struct wpa_authenticator *wpa_auth, const u8 *addr,
const u8 *pmk, size_t pmk_len, const u8 *pmkid,
int session_timeout, int akmp);

View file

@ -58,6 +58,7 @@ struct wpa_state_machine {
u8 alt_replay_counter[WPA_REPLAY_COUNTER_LEN];
u8 PMK[PMK_LEN_MAX];
unsigned int pmk_len;
u8 pmkid[PMKID_LEN]; /* valid if pmkid_set == 1 */
struct wpa_ptk PTK;
Boolean PTK_valid;
Boolean pairwise_set;
@ -90,6 +91,7 @@ struct wpa_state_machine {
unsigned int pmk_r1_name_valid:1;
#endif /* CONFIG_IEEE80211R_AP */
unsigned int is_wnmsleep:1;
unsigned int pmkid_set:1;
u8 req_replay_counter[WPA_REPLAY_COUNTER_LEN];
int req_replay_counter_used;