diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index b4e9952fe..d4122b524 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -4753,6 +4753,7 @@ static const struct global_parse_data global_fields[] = { { FUNC(os_version), CFG_CHANGED_OS_VERSION }, { STR(config_methods), CFG_CHANGED_CONFIG_METHODS }, { INT_RANGE(wps_cred_processing, 0, 2), 0 }, + { INT_RANGE(wps_cred_add_sae, 0, 1), 0 }, { FUNC(wps_vendor_ext_m1), CFG_CHANGED_VENDOR_EXTENSION }, #endif /* CONFIG_WPS */ #ifdef CONFIG_P2P diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h index 15d8c4830..abbd8c90e 100644 --- a/wpa_supplicant/config.h +++ b/wpa_supplicant/config.h @@ -745,6 +745,16 @@ struct wpa_config { */ int wps_cred_processing; + /** + * wps_cred_add_sae - Whether to enable SAE automatically for WPS + * + * 0 = only add the explicitly listed WPA2-PSK configuration + * 1 = add both the WPA2-PSK and SAE configuration and enable PMF so + * that the station gets configured in WPA3-Personal transition mode + * (supports both WPA2-Personal (PSK) and WPA3-Personal (SAE) APs). + */ + int wps_cred_add_sae; + #define MAX_SEC_DEVICE_TYPES 5 /** * sec_device_types - Secondary Device Types (P2P) diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index f1d865ccb..dd97d43a9 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -1187,6 +1187,9 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config) if (config->wps_cred_processing) fprintf(f, "wps_cred_processing=%d\n", config->wps_cred_processing); + if (config->wps_cred_add_sae) + fprintf(f, "wps_cred_add_sae=%d\n", + config->wps_cred_add_sae); if (config->wps_vendor_ext_m1) { int i, len = wpabuf_len(config->wps_vendor_ext_m1); const u8 *p = wpabuf_head_u8(config->wps_vendor_ext_m1); diff --git a/wpa_supplicant/config_winreg.c b/wpa_supplicant/config_winreg.c index 0ce1830b4..c3ab817c5 100644 --- a/wpa_supplicant/config_winreg.c +++ b/wpa_supplicant/config_winreg.c @@ -255,6 +255,8 @@ static int wpa_config_read_global(struct wpa_config *config, HKEY hk) errors++; wpa_config_read_reg_dword(hk, TEXT("wps_cred_processing"), &config->wps_cred_processing); + wpa_config_read_reg_dword(hk, TEXT("wps_cred_add_sae"), + &config->wps_cred_add_sae); #endif /* CONFIG_WPS */ #ifdef CONFIG_P2P config->p2p_ssid_postfix = wpa_config_read_reg_string( @@ -604,6 +606,8 @@ static int wpa_config_write_global(struct wpa_config *config, HKEY hk) } wpa_config_write_reg_dword(hk, TEXT("wps_cred_processing"), config->wps_cred_processing, 0); + wpa_config_write_reg_dword(hk, TEXT("wps_cred_add_sae"), + config->wps_cred_add_sae, 0); #endif /* CONFIG_WPS */ #ifdef CONFIG_P2P wpa_config_write_reg_string(hk, "p2p_ssid_postfix", diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf index d0be9371b..9a472a5ba 100644 --- a/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant/wpa_supplicant.conf @@ -282,6 +282,14 @@ fast_reauth=1 # to external program(s) #wps_cred_processing=0 +# Whether to enable SAE (WPA3-Personal transition mode) automatically for +# WPA2-PSK credentials received using WPS. +# 0 = only add the explicitly listed WPA2-PSK configuration (default) +# 1 = add both the WPA2-PSK and SAE configuration and enable PMF so that the +# station gets configured in WPA3-Personal transition mode (supports both +# WPA2-Personal (PSK) and WPA3-Personal (SAE) APs). +#wps_cred_add_sae=0 + # Vendor attribute in WPS M1, e.g., Windows 7 Vertical Pairing # The vendor attribute contents to be added in M1 (hex string) #wps_vendor_ext_m1=000137100100020001 diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c index c11d4fbd0..057927410 100644 --- a/wpa_supplicant/wps_supplicant.c +++ b/wpa_supplicant/wps_supplicant.c @@ -530,11 +530,18 @@ static int wpa_supplicant_wps_cred(void *ctx, case WPS_AUTH_WPA2PSK: ssid->auth_alg = WPA_AUTH_ALG_OPEN; ssid->key_mgmt = WPA_KEY_MGMT_PSK; + if (wpa_s->conf->wps_cred_add_sae && + cred->key_len != 2 * PMK_LEN) { + ssid->key_mgmt |= WPA_KEY_MGMT_SAE; +#ifdef CONFIG_IEEE80211W + ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL; +#endif /* CONFIG_IEEE80211W */ + } ssid->proto = WPA_PROTO_RSN; break; } - if (ssid->key_mgmt == WPA_KEY_MGMT_PSK) { + if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) { if (cred->key_len == 2 * PMK_LEN) { if (hexstr2bin((const char *) cred->key, ssid->psk, PMK_LEN)) {