From e36a5894d0c01eb4dc439b3d93c92736f407082d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 20 Jan 2020 21:15:04 +0200 Subject: [PATCH] SAE: Use H2E whenever Password Identifier is used IEEE P802.11-REVmd was modified to require H2E to be used whenever Password Identifier is used with SAE. See this document for more details of the approved changes: https://mentor.ieee.org/802.11/dcn/19/11-19-2154-02-000m-sae-anti-clogging-token.docx Signed-off-by: Jouni Malinen --- hostapd/hostapd.conf | 6 +++-- src/ap/ap_config.c | 3 ++- src/ap/ieee802_11.c | 40 ++++++++++++++++++++---------- src/ap/ieee802_11_shared.c | 3 ++- src/ap/wpa_auth_glue.c | 7 ++++++ wpa_supplicant/events.c | 3 ++- wpa_supplicant/sme.c | 8 ++++-- wpa_supplicant/wpa_supplicant.c | 9 ++++--- wpa_supplicant/wpa_supplicant.conf | 6 +++-- 9 files changed, 60 insertions(+), 25 deletions(-) diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index d76a6c7f1..168832110 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -1784,11 +1784,13 @@ own_ip_addr=127.0.0.1 #sae_confirm_immediate=0 # SAE mechanism for PWE derivation -# 0 = hunting-and-pecking loop only (default) -# 1 = hash-to-element only +# 0 = hunting-and-pecking loop only (default without password identifier) +# 1 = hash-to-element only (default with password identifier) # 2 = both hunting-and-pecking loop and hash-to-element enabled # Note: The default value is likely to change from 0 to 2 once the new # hash-to-element mechanism has received more interoperability testing. +# When using SAE password identifier, the hash-to-element mechanism is used +# regardless of the sae_pwe parameter value. #sae_pwe=0 # FILS Cache Identifier (16-bit value in hexdump format) diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index cc041441c..799d8f4da 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -441,7 +441,8 @@ int hostapd_setup_sae_pt(struct hostapd_bss_config *conf) struct hostapd_ssid *ssid = &conf->ssid; struct sae_password_entry *pw; - if (conf->sae_pwe == 0 || !wpa_key_mgmt_sae(conf->wpa_key_mgmt)) + if ((conf->sae_pwe == 0 && !hostapd_sae_pw_id_in_use(conf)) || + !wpa_key_mgmt_sae(conf->wpa_key_mgmt)) return 0; /* PT not needed */ sae_deinit_pt(ssid->pt); diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index cd6107794..5ff65b901 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -88,6 +88,7 @@ u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid) { u8 *pos = eid; int i, num, count; + int h2e_required; if (hapd->iface->current_rates == NULL) return eid; @@ -98,8 +99,10 @@ u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid) num++; if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht) num++; - if (hapd->conf->sae_pwe == 1 && - wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt)) + h2e_required = (hapd->conf->sae_pwe == 1 || + hostapd_sae_pw_id_in_use(hapd->conf) == 2) && + wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt); + if (h2e_required) num++; if (num > 8) { /* rest of the rates are encoded in Extended supported @@ -127,9 +130,7 @@ u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid) *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY; } - if (hapd->conf->sae_pwe == 1 && - wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) && - count < 8) { + if (h2e_required && count < 8) { count++; *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_SAE_H2E_ONLY; } @@ -142,6 +143,7 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid) { u8 *pos = eid; int i, num, count; + int h2e_required; if (hapd->iface->current_rates == NULL) return eid; @@ -151,8 +153,10 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid) num++; if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht) num++; - if (hapd->conf->sae_pwe == 1 && - wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt)) + h2e_required = (hapd->conf->sae_pwe == 1 || + hostapd_sae_pw_id_in_use(hapd->conf) == 2) && + wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt); + if (h2e_required) num++; if (num <= 8) return eid; @@ -183,8 +187,7 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid) *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY; } - if (hapd->conf->sae_pwe == 1 && - wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt)) { + if (h2e_required) { count++; if (count > 8) *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_SAE_H2E_ONLY; @@ -453,7 +456,9 @@ static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd, use_pt = sta->sae->tmp->h2e; } - if (status_code == WLAN_STATUS_SUCCESS) + if (rx_id) + use_pt = 1; + else if (status_code == WLAN_STATUS_SUCCESS) use_pt = 0; else if (status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT) use_pt = 1; @@ -1060,11 +1065,20 @@ static void sae_pick_next_group(struct hostapd_data *hapd, struct sta_info *sta) static int sae_status_success(struct hostapd_data *hapd, u16 status_code) { - return (hapd->conf->sae_pwe == 0 && + int sae_pwe = hapd->conf->sae_pwe; + int id_in_use; + + id_in_use = hostapd_sae_pw_id_in_use(hapd->conf); + if (id_in_use == 2) + sae_pwe = 1; + else if (id_in_use == 1 && sae_pwe == 0) + sae_pwe = 2; + + return (sae_pwe == 0 && status_code == WLAN_STATUS_SUCCESS) || - (hapd->conf->sae_pwe == 1 && + (sae_pwe == 1 && status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT) || - (hapd->conf->sae_pwe == 2 && + (sae_pwe == 2 && (status_code == WLAN_STATUS_SUCCESS || status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT)); } diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c index ab81d083e..5b14694ea 100644 --- a/src/ap/ieee802_11_shared.c +++ b/src/ap/ieee802_11_shared.c @@ -1014,7 +1014,8 @@ u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len) if (!(hapd->conf->wpa & WPA_PROTO_RSN) || !wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) || - (hapd->conf->sae_pwe != 1 && hapd->conf->sae_pwe != 2) || + (hapd->conf->sae_pwe != 1 && hapd->conf->sae_pwe != 2 && + !hostapd_sae_pw_id_in_use(hapd->conf)) || len < 3) return pos; diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c index e64304636..4927744ef 100644 --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c @@ -37,6 +37,8 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, struct hostapd_config *iconf, struct wpa_auth_config *wconf) { + int sae_pw_id; + os_memset(wconf, 0, sizeof(*wconf)); wconf->wpa = conf->wpa; wconf->wpa_key_mgmt = conf->wpa_key_mgmt; @@ -155,6 +157,11 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, FILS_CACHE_ID_LEN); #endif /* CONFIG_FILS */ wconf->sae_pwe = conf->sae_pwe; + sae_pw_id = hostapd_sae_pw_id_in_use(conf); + if (sae_pw_id == 2) + wconf->sae_pwe = 1; + else if (sae_pw_id == 1 && wconf->sae_pwe == 0) + wconf->sae_pwe = 2; } diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 8f5b21a9f..12e22e84e 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -854,6 +854,7 @@ static int rate_match(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, if (flagged && ((rate_ie[j] & 0x7f) == BSS_MEMBERSHIP_SELECTOR_SAE_H2E_ONLY)) { if (wpa_s->conf->sae_pwe == 0 && + !ssid->sae_password_id && wpa_key_mgmt_sae(ssid->key_mgmt)) { if (debug_print) wpa_dbg(wpa_s, MSG_DEBUG, @@ -1299,7 +1300,7 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, } #ifdef CONFIG_SAE - if (wpa_s->conf->sae_pwe == 1 && + if ((wpa_s->conf->sae_pwe == 1 || ssid->sae_password_id) && wpa_key_mgmt_sae(ssid->key_mgmt) && (!(ie = wpa_bss_get_ie(bss, WLAN_EID_RSNX)) || ie[1] < 1 || diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index 2d7373e55..51f8d6105 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -131,7 +131,10 @@ static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s, return NULL; } - if (wpa_s->conf->sae_pwe == 1 || wpa_s->conf->sae_pwe == 2) { + if (ssid->sae_password_id) + use_pt = 1; + + if (use_pt || wpa_s->conf->sae_pwe == 1 || wpa_s->conf->sae_pwe == 2) { bss = wpa_bss_get_bssid_latest(wpa_s, bssid); if (bss) { const u8 *rsnxe; @@ -142,7 +145,8 @@ static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s, BIT(WLAN_RSNX_CAPAB_SAE_H2E)); } - if (wpa_s->conf->sae_pwe == 1 && !use_pt) { + if ((wpa_s->conf->sae_pwe == 1 || ssid->sae_password_id) && + !use_pt) { wpa_printf(MSG_DEBUG, "SAE: Cannot use H2E with the selected AP"); return NULL; diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 9f3d6ef60..8cf148f90 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -1272,7 +1272,7 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, u8 *wpa_ie, size_t *wpa_ie_len) { struct wpa_ie_data ie; - int sel, proto; + int sel, proto, sae_pwe; const u8 *bss_wpa, *bss_rsn, *bss_rsnx, *bss_osen; if (bss) { @@ -1617,7 +1617,10 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, #ifdef CONFIG_OCV wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCV, ssid->ocv); #endif /* CONFIG_OCV */ - wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PWE, wpa_s->conf->sae_pwe); + sae_pwe = wpa_s->conf->sae_pwe; + if (ssid->sae_password_id) + sae_pwe = 1; + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PWE, sae_pwe); if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) { wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE"); @@ -1993,7 +1996,7 @@ static void wpa_s_setup_sae_pt(struct wpa_config *conf, struct wpa_ssid *ssid) if (!password) password = ssid->passphrase; - if (conf->sae_pwe == 0 || !password) { + if ((conf->sae_pwe == 0 && !ssid->sae_password_id) || !password) { /* PT derivation not needed */ sae_deinit_pt(ssid->pt); ssid->pt = NULL; diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf index 328f91a97..ec1ec0dbe 100644 --- a/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant/wpa_supplicant.conf @@ -426,11 +426,13 @@ fast_reauth=1 #sae_groups=19 20 21 # SAE mechanism for PWE derivation -# 0 = hunting-and-pecking loop only (default) -# 1 = hash-to-element only +# 0 = hunting-and-pecking loop only (default without password identifier) +# 1 = hash-to-element only (default with password identifier) # 2 = both hunting-and-pecking loop and hash-to-element enabled # Note: The default value is likely to change from 0 to 2 once the new # hash-to-element mechanism has received more interoperability testing. +# When using SAE password identifier, the hash-to-element mechanism is used +# regardless of the sae_pwe parameter value. #sae_pwe=0 # Default value for DTIM period (if not overridden in network block)