SAE: Determine H2E vs. looping when restarting SAE auth in AP mode

If hostapd had existing STA SAE state, e.g., from a previously completed
SAE authentication, a new start of a separate SAE authentication (i.e.,
receiving of a new SAE commit) ended up using some of the previous
state. This is problematic for determining whether to H2E vs. looping
since the STA is allowed (even if not really expected to) to change
between these two alternatives. This could result in trying to use H2E
when STA was using looping to derive PWE and that would result in SAE
confirm failing.

Fix this by determining whether to use H2E or looping for the restarted
authentication based on the Status Code in the new SAE commit message
instead of previously cached state information.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
This commit is contained in:
Jouni Malinen 2019-10-25 15:54:11 +03:00 committed by Jouni Malinen
parent de580bf6c4
commit 93a1e275a7

View file

@ -403,7 +403,8 @@ static void sae_set_state(struct sta_info *sta, enum sae_state state,
static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd, static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd,
struct sta_info *sta, int update) struct sta_info *sta, int update,
int status_code)
{ {
struct wpabuf *buf; struct wpabuf *buf;
const char *password = NULL; const char *password = NULL;
@ -417,6 +418,11 @@ static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd,
use_pt = sta->sae->tmp->h2e; use_pt = sta->sae->tmp->h2e;
} }
if (status_code == WLAN_STATUS_SUCCESS)
use_pt = 0;
else if (status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT)
use_pt = 1;
for (pw = hapd->conf->sae_passwords; pw; pw = pw->next) { for (pw = hapd->conf->sae_passwords; pw; pw = pw->next) {
if (!is_broadcast_ether_addr(pw->peer_addr) && if (!is_broadcast_ether_addr(pw->peer_addr) &&
os_memcmp(pw->peer_addr, sta->addr, ETH_ALEN) != 0) os_memcmp(pw->peer_addr, sta->addr, ETH_ALEN) != 0)
@ -489,13 +495,13 @@ static struct wpabuf * auth_build_sae_confirm(struct hostapd_data *hapd,
static int auth_sae_send_commit(struct hostapd_data *hapd, static int auth_sae_send_commit(struct hostapd_data *hapd,
struct sta_info *sta, struct sta_info *sta,
const u8 *bssid, int update) const u8 *bssid, int update, int status_code)
{ {
struct wpabuf *data; struct wpabuf *data;
int reply_res; int reply_res;
u16 status; u16 status;
data = auth_build_sae_commit(hapd, sta, update); data = auth_build_sae_commit(hapd, sta, update, status_code);
if (!data && sta->sae->tmp && sta->sae->tmp->pw_id) if (!data && sta->sae->tmp && sta->sae->tmp->pw_id)
return WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER; return WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER;
if (data == NULL) if (data == NULL)
@ -693,7 +699,7 @@ static void auth_sae_retransmit_timer(void *eloop_ctx, void *eloop_data)
switch (sta->sae->state) { switch (sta->sae->state) {
case SAE_COMMITTED: case SAE_COMMITTED:
ret = auth_sae_send_commit(hapd, sta, hapd->own_addr, 0); ret = auth_sae_send_commit(hapd, sta, hapd->own_addr, 0, -1);
eloop_register_timeout(0, eloop_register_timeout(0,
hapd->dot11RSNASAERetransPeriod * 1000, hapd->dot11RSNASAERetransPeriod * 1000,
auth_sae_retransmit_timer, hapd, sta); auth_sae_retransmit_timer, hapd, sta);
@ -811,7 +817,7 @@ static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
sta->sae->tmp->h2e = status_code == sta->sae->tmp->h2e = status_code ==
WLAN_STATUS_SAE_HASH_TO_ELEMENT; WLAN_STATUS_SAE_HASH_TO_ELEMENT;
ret = auth_sae_send_commit(hapd, sta, bssid, ret = auth_sae_send_commit(hapd, sta, bssid,
!allow_reuse); !allow_reuse, status_code);
if (ret) if (ret)
return ret; return ret;
sae_set_state(sta, SAE_COMMITTED, "Sent Commit"); sae_set_state(sta, SAE_COMMITTED, "Sent Commit");
@ -881,7 +887,8 @@ static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
return WLAN_STATUS_SUCCESS; return WLAN_STATUS_SUCCESS;
sta->sae->sync++; sta->sae->sync++;
ret = auth_sae_send_commit(hapd, sta, bssid, 0); ret = auth_sae_send_commit(hapd, sta, bssid, 0,
status_code);
if (ret) if (ret)
return ret; return ret;
@ -914,7 +921,8 @@ static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
return WLAN_STATUS_SUCCESS; return WLAN_STATUS_SUCCESS;
sta->sae->sync++; sta->sae->sync++;
ret = auth_sae_send_commit(hapd, sta, bssid, 1); ret = auth_sae_send_commit(hapd, sta, bssid, 1,
status_code);
if (ret) if (ret)
return ret; return ret;
@ -942,7 +950,8 @@ static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
*sta_removed = 1; *sta_removed = 1;
} else if (auth_transaction == 1) { } else if (auth_transaction == 1) {
wpa_printf(MSG_DEBUG, "SAE: Start reauthentication"); wpa_printf(MSG_DEBUG, "SAE: Start reauthentication");
ret = auth_sae_send_commit(hapd, sta, bssid, 1); ret = auth_sae_send_commit(hapd, sta, bssid, 1,
status_code);
if (ret) if (ret)
return ret; return ret;
sae_set_state(sta, SAE_COMMITTED, "Sent Commit"); sae_set_state(sta, SAE_COMMITTED, "Sent Commit");
@ -1174,7 +1183,8 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
* Authentication frame, and the commit-scalar and * Authentication frame, and the commit-scalar and
* COMMIT-ELEMENT previously sent. * COMMIT-ELEMENT previously sent.
*/ */
resp = auth_sae_send_commit(hapd, sta, mgmt->bssid, 0); resp = auth_sae_send_commit(hapd, sta, mgmt->bssid, 0,
status_code);
if (resp != WLAN_STATUS_SUCCESS) { if (resp != WLAN_STATUS_SUCCESS) {
wpa_printf(MSG_ERROR, wpa_printf(MSG_ERROR,
"SAE: Failed to send commit message"); "SAE: Failed to send commit message");
@ -1385,7 +1395,7 @@ int auth_sae_init_committed(struct hostapd_data *hapd, struct sta_info *sta)
if (sta->sae->state != SAE_NOTHING) if (sta->sae->state != SAE_NOTHING)
return -1; return -1;
ret = auth_sae_send_commit(hapd, sta, hapd->own_addr, 0); ret = auth_sae_send_commit(hapd, sta, hapd->own_addr, 0, -1);
if (ret) if (ret)
return -1; return -1;