]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
DPP2: Allow station to require or not allow PFS
authorJouni Malinen <jouni@codeaurora.org>
Sat, 28 Mar 2020 13:06:15 +0000 (15:06 +0200)
committerJouni Malinen <j@w1.fi>
Sat, 28 Mar 2020 15:23:22 +0000 (17:23 +0200)
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>
wpa_supplicant/config.c
wpa_supplicant/config_file.c
wpa_supplicant/config_ssid.h
wpa_supplicant/ctrl_iface.c
wpa_supplicant/events.c
wpa_supplicant/sme.c
wpa_supplicant/wpa_supplicant.c
wpa_supplicant/wpa_supplicant.conf
wpa_supplicant/wpa_supplicant_i.h

index e86fd7f81c74be04066c8850e98de8877b256ecb..563d18fb8ffa204a0edb408d48d05efe767a3439 100644 (file)
@@ -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) },
index 74068d66c5652ff76e0fc2a0be916a56e5d1a7fb..074b3b31a6832adddf7d64c8876ea7870f2867c7 100644 (file)
@@ -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);
index 618145e8b203101dc13d053b5c75a0a7f87115b1..c214b6c3ffa3320c02dbb8110c8b422c9c6e8799 100644 (file)
@@ -1002,6 +1002,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
         *
index a2b4ee765b6841e86e6c0dcd331f497c7a66a88a..7301d50fc66adf7d773b34b42de4c660bd633f30 100644 (file)
@@ -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);
index 3758373d4afa89e94668ccd653d5dcbea0a3a260..e8b8a9c98b4907349b96d55c63dd956f004b0c87 100644 (file)
@@ -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 &&
index 71b67e4a7f67d932df32862dc0c45bad0b57a281..a35310157417a130d3122dd234471b495b367017 100644 (file)
@@ -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);
index a01a3e748831dc56be7cbbae3ae21b334247cda6..8016fd3ac21f4a5f38b80cfc4ed5485737ad4254 100644 (file)
@@ -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);
index 591e1343f48d9f69289b79abc60db7e7dccef392..f242c3a9e0406b9fe8778f0fc0a8d36baad70cfc 100644 (file)
@@ -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
index b71e335831e58642116e0647ee2599ba41b396b4..b7cf7f4dfb3ad6c1d68354664110f38fc97ae09f 100644 (file)
@@ -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;