}
-static int sme_set_sae_group(struct wpa_supplicant *wpa_s)
+static int sme_set_sae_group(struct wpa_supplicant *wpa_s, bool external)
{
int *groups = wpa_s->conf->sae_groups;
int default_groups[] = { 19, 20, 21, 0 };
if (sae_set_group(&wpa_s->sme.sae, group) == 0) {
wpa_dbg(wpa_s, MSG_DEBUG, "SME: Selected SAE group %d",
wpa_s->sme.sae.group);
- wpa_s->sme.sae.akmp = wpa_s->key_mgmt;
+ wpa_s->sme.sae.akmp = external ?
+ wpa_s->sme.ext_auth_key_mgmt : wpa_s->key_mgmt;
return 0;
}
wpa_s->sme.sae_group_index++;
int use_pt = 0;
bool use_pk = false;
u8 rsnxe_capa = 0;
+ int key_mgmt = external ? wpa_s->sme.ext_auth_key_mgmt :
+ wpa_s->key_mgmt;
if (ret_use_pt)
*ret_use_pt = 0;
use_pk = wpa_s->sme.sae.pk;
goto reuse_data;
}
- if (sme_set_sae_group(wpa_s) < 0) {
+ if (sme_set_sae_group(wpa_s, external) < 0) {
wpa_printf(MSG_DEBUG, "SAE: Failed to select group");
goto fail;
}
if (ssid->sae_password_id &&
wpa_s->conf->sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
use_pt = 1;
- if (wpa_key_mgmt_sae_ext_key(wpa_s->key_mgmt) &&
+ if (wpa_key_mgmt_sae_ext_key(key_mgmt) &&
wpa_s->conf->sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
use_pt = 1;
#ifdef CONFIG_SAE_PK
if ((wpa_s->conf->sae_pwe == SAE_PWE_HASH_TO_ELEMENT ||
ssid->sae_password_id ||
- wpa_key_mgmt_sae_ext_key(wpa_s->key_mgmt)) &&
+ wpa_key_mgmt_sae_ext_key(key_mgmt)) &&
wpa_s->conf->sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK &&
!use_pt) {
wpa_printf(MSG_DEBUG,
}
-static bool is_sae_key_mgmt_suite(u32 suite)
+static bool is_sae_key_mgmt_suite(struct wpa_supplicant *wpa_s, u32 suite)
{
/* suite is supposed to be the selector value in host byte order with
* the OUI in three most significant octets. However, the initial
* that followed the expected byte order. Keep a workaround here to
* match that initial implementation so that already deployed use cases
* remain functional. */
- if (RSN_SELECTOR_GET(&suite) == RSN_AUTH_KEY_MGMT_SAE)
+ if (RSN_SELECTOR_GET(&suite) == RSN_AUTH_KEY_MGMT_SAE) {
+ /* Old drivers which follow initial implementation send SAE AKM
+ * for both SAE and FT-SAE connections. In that case, determine
+ * the actual AKM from wpa_s->key_mgmt. */
+ wpa_s->sme.ext_auth_key_mgmt = wpa_s->key_mgmt;
return true;
+ }
+
+ if (suite == RSN_AUTH_KEY_MGMT_SAE)
+ wpa_s->sme.ext_auth_key_mgmt = WPA_KEY_MGMT_SAE;
+ else if (suite == RSN_AUTH_KEY_MGMT_FT_SAE)
+ wpa_s->sme.ext_auth_key_mgmt = WPA_KEY_MGMT_FT_SAE;
+ else if (suite == RSN_AUTH_KEY_MGMT_SAE_EXT_KEY)
+ wpa_s->sme.ext_auth_key_mgmt = WPA_KEY_MGMT_SAE_EXT_KEY;
+ else if (suite == RSN_AUTH_KEY_MGMT_FT_SAE_EXT_KEY)
+ wpa_s->sme.ext_auth_key_mgmt = WPA_KEY_MGMT_FT_SAE_EXT_KEY;
+ else
+ return false;
- return suite == RSN_AUTH_KEY_MGMT_SAE ||
- suite == RSN_AUTH_KEY_MGMT_FT_SAE ||
- suite == RSN_AUTH_KEY_MGMT_SAE_EXT_KEY ||
- suite == RSN_AUTH_KEY_MGMT_FT_SAE_EXT_KEY;
+ return true;
}
void sme_external_auth_trigger(struct wpa_supplicant *wpa_s,
union wpa_event_data *data)
{
- if (!is_sae_key_mgmt_suite(data->external_auth.key_mgmt_suite))
+ if (!is_sae_key_mgmt_suite(wpa_s, data->external_auth.key_mgmt_suite))
return;
if (data->external_auth.action == EXT_AUTH_START) {
int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
wpa_s->sme.sae.group);
wpa_s->sme.sae_group_index++;
- if (sme_set_sae_group(wpa_s) < 0)
+ if (sme_set_sae_group(wpa_s, external) < 0)
return -1; /* no other groups enabled */
wpa_dbg(wpa_s, MSG_DEBUG, "SME: Try next enabled SAE group");
if (!external)