static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid,
const u8 *bssid, int external,
- int reuse, int *ret_use_pt)
+ int reuse, int *ret_use_pt,
+ bool *ret_use_pk)
{
struct wpabuf *buf;
size_t len;
const char *password;
struct wpa_bss *bss;
int use_pt = 0;
+ bool use_pk = false;
+ u8 rsnxe_capa = 0;
if (ret_use_pt)
*ret_use_pt = 0;
+ if (ret_use_pk)
+ *ret_use_pk = false;
#ifdef CONFIG_TESTING_OPTIONS
if (wpa_s->sae_commit_override) {
wpa_printf(MSG_DEBUG,
"SAE: Reuse previously generated PWE on a retry with the same AP");
use_pt = wpa_s->sme.sae.tmp->h2e;
+ use_pk = wpa_s->sme.sae.tmp->pk;
goto reuse_data;
}
if (sme_set_sae_group(wpa_s) < 0) {
return NULL;
}
+ bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
+ if (bss) {
+ const u8 *rsnxe;
+
+ rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
+ if (rsnxe && rsnxe[1] >= 1)
+ rsnxe_capa = rsnxe[2];
+ }
+
if (ssid->sae_password_id && wpa_s->conf->sae_pwe != 3)
use_pt = 1;
+#ifdef CONFIG_SAE_PK
+ if ((rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_PK)) &&
+ ssid->sae_password && sae_pk_valid_password(ssid->sae_password)) {
+ use_pt = 1;
+ use_pk = true;
+ }
+#endif /* CONFIG_SAE_PK */
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;
-
- rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
- if (rsnxe && rsnxe[1] >= 1)
- use_pt = !!(rsnxe[2] &
- BIT(WLAN_RSNX_CAPAB_SAE_H2E));
- }
+ use_pt = !!(rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_H2E));
if ((wpa_s->conf->sae_pwe == 1 || ssid->sae_password_id) &&
wpa_s->conf->sae_pwe != 3 &&
wpa_printf(MSG_DEBUG, "SAE: Could not pick PWE");
return NULL;
}
- if (wpa_s->sme.sae.tmp)
+ if (wpa_s->sme.sae.tmp) {
os_memcpy(wpa_s->sme.sae.tmp->bssid, bssid, ETH_ALEN);
+ if (use_pt && use_pk)
+ wpa_s->sme.sae.tmp->pk = 1;
+#ifdef CONFIG_SAE_PK
+ os_memcpy(wpa_s->sme.sae.tmp->own_addr, wpa_s->own_addr,
+ ETH_ALEN);
+ os_memcpy(wpa_s->sme.sae.tmp->peer_addr, bssid, ETH_ALEN);
+ sae_pk_set_password(&wpa_s->sme.sae, password);
+#endif /* CONFIG_SAE_PK */
+ }
reuse_data:
len = wpa_s->sme.sae_token ? 3 + wpabuf_len(wpa_s->sme.sae_token) : 0;
return NULL;
if (!external) {
wpabuf_put_le16(buf, 1); /* Transaction seq# */
- wpabuf_put_le16(buf, use_pt ? WLAN_STATUS_SAE_HASH_TO_ELEMENT :
- WLAN_STATUS_SUCCESS);
+ if (use_pk)
+ wpabuf_put_le16(buf, WLAN_STATUS_SAE_PK);
+ else if (use_pt)
+ wpabuf_put_le16(buf, WLAN_STATUS_SAE_HASH_TO_ELEMENT);
+ else
+ wpabuf_put_le16(buf,WLAN_STATUS_SUCCESS);
}
if (sae_write_commit(&wpa_s->sme.sae, buf, wpa_s->sme.sae_token,
ssid->sae_password_id) < 0) {
}
if (ret_use_pt)
*ret_use_pt = use_pt;
+ if (ret_use_pk)
+ *ret_use_pk = use_pk;
return buf;
}
if (start)
resp = sme_auth_build_sae_commit(wpa_s, ssid,
bss->bssid, 0,
- start == 2, NULL);
+ start == 2, NULL,
+ NULL);
else
resp = sme_auth_build_sae_confirm(wpa_s, 0);
if (resp == NULL) {
{
struct wpabuf *resp, *buf;
int use_pt;
+ bool use_pk;
+ u16 status;
- resp = sme_auth_build_sae_commit(wpa_s, ssid, bssid, 1, 0, &use_pt);
+ resp = sme_auth_build_sae_commit(wpa_s, ssid, bssid, 1, 0, &use_pt,
+ &use_pk);
if (!resp) {
wpa_printf(MSG_DEBUG, "SAE: Failed to build SAE commit");
return -1;
}
wpa_s->sme.seq_num++;
+ if (use_pk)
+ status = WLAN_STATUS_SAE_PK;
+ else if (use_pt)
+ status = WLAN_STATUS_SAE_HASH_TO_ELEMENT;
+ else
+ status = WLAN_STATUS_SUCCESS;
sme_external_auth_build_buf(buf, resp, wpa_s->own_addr,
- bssid, 1, wpa_s->sme.seq_num,
- use_pt ? WLAN_STATUS_SAE_HASH_TO_ELEMENT :
- WLAN_STATUS_SUCCESS);
+ bssid, 1, wpa_s->sme.seq_num, status);
wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1, 0, 0);
wpabuf_free(resp);
wpabuf_free(buf);
}
if (status_code != WLAN_STATUS_SUCCESS &&
- status_code != WLAN_STATUS_SAE_HASH_TO_ELEMENT)
+ status_code != WLAN_STATUS_SAE_HASH_TO_ELEMENT &&
+ status_code != WLAN_STATUS_SAE_PK)
return -1;
if (auth_transaction == 1) {
"SAE: Unexpected use of status code 0 in SAE commit when H2E was expected");
return -1;
}
- if (wpa_s->sme.sae.tmp && !wpa_s->sme.sae.tmp->h2e &&
+ if (wpa_s->sme.sae.tmp &&
+ (!wpa_s->sme.sae.tmp->h2e || wpa_s->sme.sae.tmp->pk) &&
status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT) {
wpa_printf(MSG_DEBUG,
"SAE: Unexpected use of status code for H2E in SAE commit when H2E was not expected");
return -1;
}
+ if (wpa_s->sme.sae.tmp && !wpa_s->sme.sae.tmp->pk &&
+ status_code == WLAN_STATUS_SAE_PK) {
+ wpa_printf(MSG_DEBUG,
+ "SAE: Unexpected use of status code for PK in SAE commit when PK was not expected");
+ return -1;
+ }
if (groups && groups[0] <= 0)
groups = NULL;
res = sae_parse_commit(&wpa_s->sme.sae, data, len, NULL, NULL,
groups, status_code ==
- WLAN_STATUS_SAE_HASH_TO_ELEMENT);
+ WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
+ status_code == WLAN_STATUS_SAE_PK);
if (res == SAE_SILENTLY_DISCARD) {
wpa_printf(MSG_DEBUG,
"SAE: Drop commit message due to reflection attack");