diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index ab668759e..33b35056b 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -12,6 +12,7 @@ #include "utils/uuid.h" #include "utils/ip_addr.h" #include "common/ieee802_1x_defs.h" +#include "common/sae.h" #include "crypto/sha1.h" #include "rsn_supp/wpa.h" #include "eap_peer/eap.h" @@ -2765,6 +2766,9 @@ void wpa_config_free_ssid(struct wpa_ssid *ssid) dl_list_del(&psk->list); bin_clear_free(psk, sizeof(*psk)); } +#ifdef CONFIG_SAE + sae_deinit_pt(ssid->pt); +#endif /* CONFIG_SAE */ bin_clear_free(ssid, sizeof(*ssid)); } @@ -3104,6 +3108,15 @@ int wpa_config_set(struct wpa_ssid *ssid, const char *var, const char *value, } ret = -1; } +#ifdef CONFIG_SAE + if (os_strcmp(var, "ssid") == 0 || + os_strcmp(var, "psk") == 0 || + os_strcmp(var, "sae_password") == 0 || + os_strcmp(var, "sae_password_id") == 0) { + sae_deinit_pt(ssid->pt); + ssid->pt = NULL; + } +#endif /* CONFIG_SAE */ break; } if (i == NUM_SSID_FIELDS) { diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h index df5e9a2c5..98db1fe1a 100644 --- a/wpa_supplicant/config_ssid.h +++ b/wpa_supplicant/config_ssid.h @@ -213,6 +213,8 @@ struct wpa_ssid { */ char *sae_password_id; + struct sae_pt *pt; + /** * ext_psk - PSK/passphrase name in external storage * diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index ca8e1cc0b..39f69be63 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -1932,6 +1932,36 @@ int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s) } +static void wpa_s_setup_sae_pt(struct wpa_config *conf, struct wpa_ssid *ssid) +{ +#ifdef CONFIG_SAE + int *groups = conf->sae_groups; + int default_groups[] = { 19, 20, 21, 0 }; + const char *password; + + if (!groups || groups[0] <= 0) + groups = default_groups; + + password = ssid->sae_password; + if (!password) + password = ssid->passphrase; + + if (conf->sae_pwe == 0 || !password) { + /* PT derivation not needed */ + sae_deinit_pt(ssid->pt); + ssid->pt = NULL; + return; + } + + if (ssid->pt) + return; /* PT already derived */ + ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len, + (const u8 *) password, os_strlen(password), + ssid->sae_password_id); +#endif /* CONFIG_SAE */ +} + + static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit); /** @@ -1978,6 +2008,10 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, } else if (wpa_s->current_bss && wpa_s->current_bss != bss) { os_get_reltime(&wpa_s->roam_start); } + } else { +#ifdef CONFIG_SAE + wpa_s_setup_sae_pt(wpa_s->conf, ssid); +#endif /* CONFIG_SAE */ } if (rand_style > 0 && !wpa_s->reassoc_same_ess) { @@ -3984,8 +4018,10 @@ void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s, wpa_s->disconnected = 0; wpa_s->reassociate = 1; wpa_s->last_owe_group = 0; - if (ssid) + if (ssid) { ssid->owe_transition_bss_select_count = 0; + wpa_s_setup_sae_pt(wpa_s->conf, ssid); + } if (wpa_s->connect_without_scan || wpa_supplicant_fast_associate(wpa_s) != 1) {