aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouni Malinen <jouni@codeaurora.org>2020-03-28 13:06:15 (GMT)
committerJouni Malinen <j@w1.fi>2020-03-28 15:23:22 (GMT)
commit5058f771d917a5683b0c9a6eca3ddc4519ff901f (patch)
treed0c494c59f76d93375edea797cf47b345e0a2a20
parent7c021dec3a95803fc129d8533adcaeea82910c9c (diff)
downloadhostap-5058f771d917a5683b0c9a6eca3ddc4519ff901f.zip
hostap-5058f771d917a5683b0c9a6eca3ddc4519ff901f.tar.gz
hostap-5058f771d917a5683b0c9a6eca3ddc4519ff901f.tar.bz2
DPP2: Allow station to require or not allow PFS
The new wpa_supplicant network profile parameter dpp_pfs can be used to specify how PFS is applied to associations. The default behavior (dpp_pfs=0) remains same as it was previously, i.e., try to use PFS if the AP supports it. PFS use can now be required (dpp_pfs=1) or disabled (dpp_pfs=2). This is also working around an interoperability issue of DPP R2 STA with certain hostapd builds that included both OWE and DPP functionality. That issue was introduced by commit 09368515d130 ("OWE: Process Diffie-Hellman Parameter element in AP mode") and removed by commit 16a4e931f03e ("OWE: Allow Diffie-Hellman Parameter element to be included with DPP"). hostapd builds between those two commits would reject DPP association attempt with PFS. The new wpa_supplicant default (dpp_pfs=0) behavior is to automatically try to connect again with PFS disabled if that happens. Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
-rw-r--r--wpa_supplicant/config.c1
-rw-r--r--wpa_supplicant/config_file.c1
-rw-r--r--wpa_supplicant/config_ssid.h16
-rw-r--r--wpa_supplicant/ctrl_iface.c1
-rw-r--r--wpa_supplicant/events.c37
-rw-r--r--wpa_supplicant/sme.c4
-rw-r--r--wpa_supplicant/wpa_supplicant.c3
-rw-r--r--wpa_supplicant/wpa_supplicant.conf6
-rw-r--r--wpa_supplicant/wpa_supplicant_i.h1
9 files changed, 68 insertions, 2 deletions
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index e86fd7f..563d18f 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -2570,6 +2570,7 @@ static const struct parse_data ssid_fields[] = {
{ STR_LEN(dpp_netaccesskey) },
{ INT(dpp_netaccesskey_expiry) },
{ STR_LEN(dpp_csign) },
+ { INT_RANGE(dpp_pfs, 0, 2) },
#endif /* CONFIG_DPP */
{ INT_RANGE(owe_group, 0, 65535) },
{ INT_RANGE(owe_only, 0, 1) },
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index 74068d6..074b3b3 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -928,6 +928,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
STR(dpp_netaccesskey);
INT(dpp_netaccesskey_expiry);
STR(dpp_csign);
+ INT(dpp_pfs);
#endif /* CONFIG_DPP */
INT(owe_group);
INT(owe_only);
diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h
index 618145e..c214b6c 100644
--- a/wpa_supplicant/config_ssid.h
+++ b/wpa_supplicant/config_ssid.h
@@ -1003,6 +1003,22 @@ struct wpa_ssid {
size_t dpp_csign_len;
/**
+ * dpp_pfs - DPP PFS
+ * 0: allow PFS to be used or not used
+ * 1: require PFS to be used (note: not compatible with DPP R1)
+ * 2: do not allow PFS to be used
+ */
+ int dpp_pfs;
+
+ /**
+ * dpp_pfs_fallback - DPP PFS fallback selection
+ *
+ * This is an internally used variable (i.e., not used in external
+ * configuration) to track state of the DPP PFS fallback mechanism.
+ */
+ int dpp_pfs_fallback;
+
+ /**
* owe_group - OWE DH Group
*
* 0 = use default (19) first and then try all supported groups one by
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index a2b4ee7..7301d50 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -8106,6 +8106,7 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
wpa_s->dpp_resp_retry_time = 0;
#ifdef CONFIG_DPP2
wpas_dpp_chirp_stop(wpa_s);
+ wpa_s->dpp_pfs_fallback = 0;
#endif /* CONFIG_DPP2 */
#ifdef CONFIG_TESTING_OPTIONS
os_memset(dpp_pkex_own_mac_override, 0, ETH_ALEN);
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 3758373..e8b8a9c 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -3196,6 +3196,10 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
#ifdef CONFIG_MBO
wpas_mbo_check_pmf(wpa_s, bss, wpa_s->current_ssid);
#endif /* CONFIG_MBO */
+
+#ifdef CONFIG_DPP2
+ wpa_s->dpp_pfs_fallback = 0;
+#endif /* CONFIG_DPP2 */
}
@@ -4364,6 +4368,39 @@ static void wpas_event_assoc_reject(struct wpa_supplicant *wpa_s,
}
#endif /* CONFIG_OWE */
+#ifdef CONFIG_DPP2
+ /* Try to follow AP's PFS policy. WLAN_STATUS_ASSOC_DENIED_UNSPEC is
+ * the status code defined in the DPP R2 tech spec.
+ * WLAN_STATUS_AKMP_NOT_VALID is addressed in the same manner as an
+ * interoperability workaround with older hostapd implementation. */
+ if (wpa_s->current_ssid &&
+ wpa_s->current_ssid->key_mgmt == WPA_KEY_MGMT_DPP &&
+ wpa_s->current_ssid->dpp_pfs == 0 &&
+ (data->assoc_reject.status_code ==
+ WLAN_STATUS_ASSOC_DENIED_UNSPEC ||
+ data->assoc_reject.status_code == WLAN_STATUS_AKMP_NOT_VALID)) {
+ struct wpa_ssid *ssid = wpa_s->current_ssid;
+ struct wpa_bss *bss = wpa_s->current_bss;
+
+ wpa_s->current_ssid->dpp_pfs_fallback ^= 1;
+ if (!bss)
+ bss = wpa_supplicant_get_new_bss(wpa_s, bssid);
+ if (!bss || wpa_s->dpp_pfs_fallback) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Updated PFS policy for next try");
+ wpas_connection_failed(wpa_s, bssid);
+ wpa_supplicant_mark_disassoc(wpa_s);
+ return;
+ }
+ wpa_printf(MSG_DEBUG, "DPP: Try again with updated PFS policy");
+ wpa_s->dpp_pfs_fallback = 1;
+ wpas_connect_work_done(wpa_s);
+ wpa_supplicant_mark_disassoc(wpa_s);
+ wpa_supplicant_connect(wpa_s, bss, ssid);
+ return;
+ }
+#endif /* CONFIG_DPP2 */
+
#ifdef CONFIG_MBO
if (data->assoc_reject.status_code ==
WLAN_STATUS_DENIED_POOR_CHANNEL_CONDITIONS &&
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index 71b67e4..a353101 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -1793,7 +1793,9 @@ void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode,
#ifdef CONFIG_DPP2
if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP && wpa_s->current_ssid &&
- wpa_s->current_ssid->dpp_netaccesskey) {
+ wpa_s->current_ssid->dpp_netaccesskey &&
+ wpa_s->current_ssid->dpp_pfs != 2 &&
+ !wpa_s->current_ssid->dpp_pfs_fallback) {
struct wpa_ssid *ssid = wpa_s->current_ssid;
dpp_pfs_free(wpa_s->dpp_pfs);
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index a01a3e7..8016fd3 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -3071,7 +3071,8 @@ static u8 * wpas_populate_assoc_ies(
#ifdef CONFIG_DPP2
if (wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP &&
- ssid->dpp_netaccesskey) {
+ ssid->dpp_netaccesskey &&
+ ssid->dpp_pfs != 2 && !ssid->dpp_pfs_fallback) {
dpp_pfs_free(wpa_s->dpp_pfs);
wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
ssid->dpp_netaccesskey_len);
diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
index 591e134..f242c3a 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -1461,6 +1461,12 @@ fast_reauth=1
# 1-65535 = DH Group to use for FILS PFS
#fils_dh_group=0
+# DPP PFS
+# 0: allow PFS to be used or not used (default)
+# 1: require PFS to be used (note: not compatible with DPP R1)
+# 2: do not allow PFS to be used
+#dpp_pfs=0
+
# MAC address policy
# 0 = use permanent MAC address
# 1 = use random MAC address for each ESS connection
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index b71e335..b7cf7f4 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -1273,6 +1273,7 @@ struct wpa_supplicant {
size_t dpp_last_ssid_len;
#ifdef CONFIG_DPP2
struct dpp_pfs *dpp_pfs;
+ int dpp_pfs_fallback;
struct wpabuf *dpp_presence_announcement;
struct dpp_bootstrap_info *dpp_chirp_bi;
int dpp_chirp_freq;